2014-10-23 4 views
3

В следующем коде:Реализация Iterable путем возврата итератора над подтипом

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 ... 
    } 
} 

Я получаю сообщение об ошибке в указанном месте, поскольку foos.iterator() возвращает Iterable<Foo>, а не Iterable<Bar>. К сожалению, простой бросок не будет работать:

return (Iterator<Bar>) foos.iterator(); // Error: Cannot cast ... 

Java также не позволяет мне изменить определение BarIterable к

public class BarIterable implements Iterable<? extends Bar> { ... // Error: A supertype may not specify any wildcard 

Что такое хороший способ решить эту проблему, которая делает не включают реализацию Iterable<Foo> (реализация Iterable происходит из другого интерфейса, который не знает о Foo)?

Должен ли я написать себе оболочку Iterator класса, которая «распаковывает» каждое значение?

+0

Я не уверен, но похоже, что вы реализуете наследование и эта строка 'общественного класса BarIterable реализует Iterable ' вместо этого следует 'общественного класса BarIterable расширяет Iterable ', если я не ошибаюсь. –

+1

@AlvinBunk 'Iterable' - это интерфейс, поэтому мне определенно нужно использовать' tools ', а не 'extends'. –

+0

Как вы получаете 'foos'? –

ответ

5

С Foo является подтипом Bar, вы можете просто указать List.

return ((List<Bar>)(List<? extends Bar>) foos).iterator(); 

и подавлять предупреждения.

Редактировать Маркус А .:

Или, вы можете бросить итератор непосредственно с использованием промежуточного-Cast-трик:

return (Iterator<Bar>)(Iterator<? extends Bar>) foos.iterator(); 

Конец редактировать


С помощью Java 8 вы можете перебирать элементы и создавать новый тип ListBar.

@Override 
public Iterator<Bar> iterator() { 
    return foos.stream().<Bar>map((foo) -> foo /* considered a Bar */).collect(Collectors.toList()).iterator(); 
} 

но вы делаете много промежуточных операций только для просмотра List из точки А тип супер зрения.

+1

Мы идем! Потрясающие! Я пробовал листинг списков, но это не позволяло мне это делать, но я не знал об этом трюке, чтобы косвенный листинг через промежуточный листинг, используя '? extends'. Ницца! Благодаря! –

+0

Собственно, вы можете сделать итератор прямо так! –

Смежные вопросы