An Iterable should not implement the Iterator interface or return this as an Iterator. The
reason is that Iterator represents the iteration process itself, while Iterable represents the object we want to iterate
over.
The Iterator instance encapsulates state information of the iteration process, such as the current and next element. Consequently,
distinct iterations require distinct Iterator instances, for which Iterable provides the factory method
Iterable.iterator().
This rule raises an issue when the Iterable.iterator() of a class implementing both Iterable and Iterator
returns this.
The Iterable.iterator() method returning the same Iterator instance many times would have the following effects:
for loops with iterators over the same object, only the first one would iterate,
and the others would do nothing.
class FooIterator implements Iterator<Foo>, Iterable<Foo> {
private Foo[] seq;
private int idx = 0;
public boolean hasNext() {
return idx < seq.length;
}
public Foo next() {
return seq[idx++];
}
public Iterator<Foo> iterator() {
return this; // Noncompliant
}
// ...
}
class FooSequence implements Iterable<Foo> {
private Foo[] seq;
public Iterator<Foo> iterator() {
return new Iterator<Foo>() { // Compliant
private int idx = 0;
public boolean hasNext() {
return idx < seq.length;
}
public Foo next() {
return seq[idx++];
}
};
}
// ...
}