问题描述
我有一个用于各种类的接口,所有这些接口都应该实现Iterator,所以我有类似于
public接口A扩展了Iterable< A> {... otherMethods()...}
然而,对于具体的类,这意味着我必须使用
public class B implements A {public Iterator< A> iterator(){...}}
当我更喜欢(或者至少,更喜欢)使用 public Iterator< B>因为这个类的具体用法可以有明确的类型(如果我想让那些不在接口中的方法可用或者其他的方法)应该永远不会出现吗?或者它的设计很糟糕?如果是这样的话?
另一方面,使用Iterator接口
public interface A extends Iterator< A> {... otherMethods()...}
具体类可以很好地编译
public class B implements A {public B next() {...}}
什么给予?
$ b
至于泛型,我碰到了相同的墙,而且我有两个选择。我们知道的一个选项是。
paramaterize答:
公共接口A< T扩展A>扩展Iterable< T>
然后:
public class B实现了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){}
//这里你必须和Super一起去,因为Super没有参数化
//在这里允许一个Sub并且仍然覆盖这个方法。
$ / code>
类似于协方差,您不能声明<$ c类型的变量$ c> Iterator< A> ,然后在它中分配一个 Iterator< B>
,即使B扩展A也是如此。
$ b
另一个选择是与实际情况相符,即进一步的实现/子类仍然会引用A。
I have an interface for a variety of classes, all of which should implement Iterator, so I have something like
public interface A extends Iterable<A> { ...otherMethods()... }
For the concrete classes, however, this means I must use
public class B implements A { public Iterator<A> iterator() {...} }
when I'd prefer (or at least, think I'd prefer) to use public Iterator<B> iterator() {...}
so that concrete use of the class could have the explicit type (in case I wanted methods that weren't in the interface to be available, or some such. Maybe that should never come up? Or it's poor design if it does?
The flipside is that using the Iterator interface
public interface A extends Iterator<A> { ...otherMethods()... }
the concrete classes compile just fine with
public class B implements A { public B next() {...} }
What gives?
The concrete class compiles fine because B extends A, and since Java 5 a return type on a subclass can be a subclass of the return type on the superclass.
As for the generic, I have hit the same wall, and you have two options that I know of.
One is to paramaterize A:
public interface A<T extends A> extends Iterable<T>
then:
public class B implements A<B>
However, that has a disadvantage that you will need to give a parameter of A, instead of having it fixed, even if you want A:
private class NoOneSees implements A<A>
As to the question of if you actually want Iterator<B>
, in the case of an Iterable, most likely that is preferable, and considering that these are interfaces, the need to redeclare the parameter is probably reasonable. It gets a little more complicated if you start inheriting concrete classes, and for things that have meaning other than an Iterable, where you may want covariance. For example:
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.
}
Similarly for covariance, you can't declare a variable of type Iterator<A>
and then assign an Iterator<B>
in it, even if B extends A.
The other option is live with the fact that further implementation/subclasses will still reference A.
这篇关于java迭代器/可迭代子接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!