通过在子类型上返回 Iterator 来实现 Iterable
Posted
技术标签:
【中文标题】通过在子类型上返回 Iterator 来实现 Iterable【英文标题】:Implementing Iterable by returning an Iterator over a sub-type 【发布时间】:2014-12-19 12:52:41 【问题描述】:在以下代码中:
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-implementation 来自另一个不了解 Foo 的接口)的解决此问题的好方法是什么?
我是否必须为自己编写一个“解包”每个值的包装迭代器类?
【问题讨论】:
我不确定,但看起来您正在实现继承,并且这一行public class BarIterable implements Iterable<Bar>
应该改为 public class BarIterable extends Iterable<Bar>
,除非我弄错了。
@AlvinBunk Iterable
是一个接口,所以我肯定需要使用implements
,而不是extends
。
你是怎么得到foos
的?
好的,你能发布更多你的代码以便我在 Eclipse 中试用吗?
你不能把你的foos
改成List<Bar> foos
吗?
【参考方案1】:
由于Foo
是Bar
的子类型,您可以只转换List
。
return ((List<Bar>)(List<? extends Bar>) foos).iterator();
并抑制警告。
由 Markus A. 编辑:
或者,您可以使用中间转换技巧直接转换迭代器:
return (Iterator<Bar>)(Iterator<? extends Bar>) foos.iterator();
结束编辑
使用 Java 8,您可以对元素进行流式传输并构造一个新的 List
类型为 Bar
。
@Override
public Iterator<Bar> iterator()
return foos.stream().<Bar>map((foo) -> foo /* considered a Bar */).collect(Collectors.toList()).iterator();
但您执行大量中间操作只是为了从超类型的角度查看 List
。
【讨论】:
我们去!惊人的!我正在尝试列表转换,但它没有让我这样做,但我不知道使用? extends
通过中间转换间接转换转换的技巧。好的!谢谢!
其实你可以直接这样转换迭代器!以上是关于通过在子类型上返回 Iterator 来实现 Iterable的主要内容,如果未能解决你的问题,请参考以下文章