通过在子类型上返回 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&lt;Foo&gt; 而不是Iterable&lt;Bar&gt;,因此我在指定位置出现错误。不幸的是,简单的演员阵容是行不通的:

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&lt;Foo&gt;(Iterable-implementation 来自另一个不了解 Foo 的接口)的解决此问题的好方法是什么?

我是否必须为自己编写一个“解包”每个值的包装迭代器类?

【问题讨论】:

我不确定,但看起来您正在实现继承,并且这一行 public class BarIterable implements Iterable&lt;Bar&gt; 应该改为 public class BarIterable extends Iterable&lt;Bar&gt;,除非我弄错了。 @AlvinBunk Iterable 是一个接口,所以我肯定需要使用implements,而不是extends 你是怎么得到foos的? 好的,你能发布更多你的代码以便我在 Eclipse 中试用吗? 你不能把你的foos改成List&lt;Bar&gt; foos吗? 【参考方案1】:

由于FooBar 的子类型,您可以只转换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的主要内容,如果未能解决你的问题,请参考以下文章

traits的介绍

QT迭代器 QVector<int>::iterator it;

当您通过标签栏返回视图控制器时卡在子视图上

Apex 中的自定义迭代器

Iterator迭代器

Map的迭代