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?

+3


source to share


1 answer


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.

+5


source







All Articles