Implementing Iterable by Returning an Iterator by Subtype
In the following code:
public class Bar { ... }
public class Foo extends Bar { ... }
public class BarIterable implements Iterable<Bar> {
List<Foo> foos = ...
@Override
public Iterator<Bar> iterator() {
return foos.iterator(); // Error: Type mismatch ...
}
}
I am getting an error at the specified position as it foos.iterator()
returns Iterable<Foo>
, not Iterable<Bar>
. Unfortunately, a simple broadcast won't work:
return (Iterator<Bar>) foos.iterator(); // Error: Cannot cast ...
Java also prevents me from changing the definition BarIterable
to
public class BarIterable implements Iterable<? extends Bar> { ... // Error: A supertype may not specify any wildcard
What's a good way to solve this problem that doesn't include an implementation Iterable<Foo>
instead (the Iterable implementation comes from another interface that doesn't know about Foo)?
Should I write myself a wrapper Iterator class that "unpacks" each value?
source to share
Since it Foo
is a subtype Bar
, you can simply click List
.
return ((List<Bar>)(List<? extends Bar>) foos).iterator();
and suppress warnings.
Edit Markus A .:
Or, you can directly merge the iterator with an intermediate trick:
return (Iterator<Bar>)(Iterator<? extends Bar>) foos.iterator();
Finish editing
With Java 8, you can stream over elements and create a new List
type Bar
.
@Override
public Iterator<Bar> iterator() {
return foos.stream().<Bar>map((foo) -> foo /* considered a Bar */).collect(Collectors.toList()).iterator();
}
but you are doing a lot of intermediate view-only operations List
from a super-type perspective.
source to share