我有各种类的接口,所有这些都应该实现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() {...} }
是什么给出了?
答案 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会想要返回与自身无关的事物的迭代器。