java iterator / iterable子接口

时间:2009-09-03 16:57:36

标签: java generics interface iterator iterable

我有各种类的接口,所有这些都应该实现Iterator,所以我有类似的东西

public interface A extends Iterable<A> { ...otherMethods()... }

但是,对于具体的类,这意味着我必须使用

public class B implements A { public Iterator<A> iterator() {...} }

当我更喜欢(或者至少认为我更喜欢)使用public Iterator<B> iterator() {...}时,使用该类的具体用法可以具有显式类型(如果我想要的方法不在接口是可用的,还是一些这样的。也许这应该永远不会出现?或者它的设计是否很差?

另一方面是使用Iterator接口

public interface A extends Iterator<A> { ...otherMethods()... }

使用

编译具体类
public class B implements A { public B next() {...} }

是什么给出了?

5 个答案:

答案 0 :(得分:2)

卡尔是对的,我的第一个答案没有编译,但似乎这样。不确定这是不是你想要的。

public interface A<T extends A> extends Iterable<T> {

}

public class B implements A<B> {

    @Override
    public Iterator<B> iterator() {
        return null;
    }

答案 1 :(得分:1)

具体类编译得很好,因为B扩展了A,而且从Java 5开始,子类上的返回类型可以是超类上返回类型的子类。

至于通用,我碰到了同样的墙,你知道我有两个选择。

一个是A:

 public interface A<T extends A> extends Iterable<T>

然后:

public class B implements A<B>

然而,即使您想要A:

,也有一个缺点,就是您需要给出A的参数,而不是修复它。
private class NoOneSees implements A<A>

关于你是否真的想要Iterator<B>的问题,在Iterable的情况下,最有可能是优选的,并且考虑到这些是接口,重新声明参数的需要可能是合理的。如果你开始继承具体的类,并且对于具有除Iterable之外的意义的东西,你可能想要协方差,它会变得有点复杂。例如:

public interface Blah<T> {
    void blah(T param);
}

public class Super implements Blah<Super> {
    public void blah(Super param) {}
}

public class Sub extends Super {
    public void blah(Super param) {}
   //Here you have to go with Super because Super is not paramaterized
   //to allow a Sub here and still be overriding the method.
}

同样,对于协方差,您不能声明Iterator<A>类型的变量,然后在其中分配Iterator<B>,即使B扩展为A.

另一个选项是实时的,即进一步的实现/子类仍将引用A。

答案 2 :(得分:1)

其他答案有正确的要点 - 但你会通过将通用类型声明为

来获得正确的机制
A<T extends A<T>>

这会强制一个类返回一个自己类型或更低类型的迭代器 - 所以你可以声明

class B implements A<B>

但不是

class B implements A<A>

我怀疑它更接近你想要的(即实现必须通过自己返回迭代器,而不是简单地超过A)。

请注意,您使用Iterator vs Iterable的体验源于泛型类型缺乏协方差; B 的实例A,但Iterator<B> Iterator<A>

答案 3 :(得分:0)

我想这就是你想要的:

public interface A<T extends A<?>>  extends Iterable<T>

public class B implements A<B> {
  public Iterator<B> iterator() {...}
}

答案 4 :(得分:0)

您的设计决策是您自己的,但我想不出设计中每个类实现Iterable的任何原因。集合中必须包含某种东西,但实际上并不是集合本身。我会仔细研究基本设计。也许一些iterables会想要返回与自身无关的事物的迭代器。