Blake Davenport
Blake Davenport

Reputation: 1

StringEnumeration (Enumeration in General)

Ok so the goal of the class is to override the two methods inside of the Enumeration object class. I believe my hasNextElement() method should work, any pointers on that would be appreciated. I, however, am having troubles with the nextElement() method. Excuse the improper commenting throught the class but the goal of nextElement() is to return one character at a time. I figured its just a simple loop but netBeans keeps giving me incompatible dataTypes, which makes sense because its a String method not a Char method. So I change it to char and I get

nextElement() in StringEnumeration cannot implement nextElement() in Enumeration return type char is not compatible with String where E is a type-variable:

Any help would be greatly appreciated. Do remember I am a beginner programmer so I may have done something wrong that is easily fixable.

public class StringEnumeration implements Enumeration<String> {

    public String value;

    public StringEnumeration(String initialValue) throws InvalidStringException {
        if (initialValue == null || initialValue.length() == 0) {
            throw new InvalidStringException("initialValue is either null or 0");
        }

        this.value = initialValue;
    }

    @Override
    public boolean hasMoreElements() {
        return value.length() != 0 || value != null;
    }

    @Override
    public String nextElement() {
        StringBuffer test = new StringBuffer(value);
        for (int i = 0; i < value.length(); i++) {
            return test.charAt(i);
        }

    }
}

Upvotes: 0

Views: 678

Answers (4)

Prahalad Deshpande
Prahalad Deshpande

Reputation: 4767

//know acess modifiers well...
private String value;

private Integer currentPosition;

public StringEnumeration(String initialValue) throws InvalidStringException {
    if (initialValue == null || initialValue.length() == 0) {
        throw new InvalidStringException("initialValue is either null or 0");
    }

    this.value = initialValue;
} 

//you would return false when the list is empty OR the current position is
//past the end of the string
@Override
public boolean hasMoreElements() {
    return value.length() != 0 || currentPosition < value.length();
}

//you would return the character at the current position
@Override
public char nextElement() {
    return value.charAt(currentPosition++);

}

Upvotes: 1

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477200

I think what you intend to implement is an Iterator<T> over the characters of a given string:

public class StringEnumeration implements Iterator<Character> {

    private final String value;
    private int index = 0;

    public StringEnumeration(String initialValue) {
        if(initialValue == null) {
            this.value = "";
        } else {
            this.value = initialValue;
        }
    }

    @Override
    public boolean hasNext() {
        return index < value.length();
    }

    @Override
    public Character next() {
        try {
            return test.charAt(this.index);
        } finally {
            this.index++;
        }
    }

    @Override
    public void remove() {
        //can be done. Necessary?
    }

}

(You can use an Enumeration<T> by simply replacing Iterator<Character> with Enumeration<Character>; and hasNext and next with hasMoreElements and nextElement and remove the remove method.

This iterator considers that the null String and the empty string "" contain both zero characters.

An iterator needs to store a state in the iteration process: the index of the character to enumerate. Initially the index is set to 0. After each item, the index is incremented.

Furthermore the test is simply whether the value has already reached the end of the String.

The main problem with your code is the following:

@Override
public String nextElement() {
    StringBuffer test = new StringBuffer(value);
    for (int i = 0; i < value.length(); i++) {
        return test.charAt(i);
    }

}

You use a for-loop but with a return statement. If you thus ask for the nextElement Java will start iterating and immediately return the first character. Furthermore this probably won't compile since the Java compiler can't figureout test has at least one element and thus it is possible that the for loop is never executed.

Other advice

Please always make fields private. By making fields public, a class can no longer guarantee the consistency of its state.

Furthermore Iterator is a modern version of Enumeration (although there is some discussion about this).

Upvotes: 1

RealSkeptic
RealSkeptic

Reputation: 34638

Your implementation has several problems.

First, in Enumeration<E> the E is not the type the enumeration is working on. It's the type that the nextElement() method is supposed to return. So an Enumeration<String> has a nextElement() method that returns String. But your implementation returns the result of charAt() - a method that returns the primitive char, not a String! You either have to return some sort of string (maybe a single-char string like "m") or a Character (because you can't make E a primitive type like char).


The next problem is that your hasNextElement() method is not actually correct. An Enumeration is intended to give you one element (character, in your case) of the data at a time, and each time you call nextElement() it moves ahead towards the end of the data. so hasNextElement() has to return true based on whether or not there is still another element to go through. Your implementation, however, will always return true for the same string. It will not give an indication when to stop calling nextElement().


Last, your nextElement() somehow thinks that it's going to return all the elements at the same time. This cannot work. An Enumeration can only give one element each time you call nextElement(). So using a loop inside it makes no sense. The proper way to do this is to keep state inside the Enumeration object, say a variable named next, that indicates where the next element is. Each time the caller calls nextElement(), you take that element, advance next, and return the element. One element at a time, no loops. The actual loop will be created by whoever is using the Enumeration, not by the Enumeration itself.

It is also this next field (or whatever you want to call it) that can help you to create a proper hasMoreElements() method. If the next reaches beyond the end of the string, hasMoreElements() has to return false, and nextElement() has to throw NoSuchElementException.

Upvotes: 1

JP Moresmau
JP Moresmau

Reputation: 7403

The easiest is to keep the index you're at as a variable in the enumeration:

// we return characters 
public class StringEnumeration implements Enumeration<Character> {
    // the value
    private String value;
    // current index
    private int idx=0;

    public StringEnumeration(String initialValue) throws IllegalArgumentException {
        if (initialValue == null || initialValue.length() == 0) {
            throw new IllegalArgumentException("initialValue is either null or 0");
        }

        this.value = initialValue;
    }

    @Override
    public boolean hasMoreElements() {
        // can we still read
        return idx<value.length();
    }

    @Override
    public Character nextElement() {
        // get current char and increment index
        return value.charAt(idx++);
    }
}

Upvotes: 1

Related Questions