理想情况下,它应该是这样的(上下文无关紧要):
public interface myInterface extends Iterable<Point>, Iterable<Segment> { ... }
但是在Java中是不允许的。我怎样才能达到这种行为呢?
遗憾的是,您不能。在Java中,不能有两个具有以下签名的方法:
Iterator<Point> iterator();
Iterator<Segment> iterator();
如前所述,这是不可能的。最好使用委托而不是像这样的多重实现:
public interface MyInterface {
Iterable<Point> points();
Iterable<Segment> segments();
}
所以你可以用来迭代:
MyInterface my = ...;
for (Point p : my.points()) {
...
}
for (Segment s : my.segments()) {
...
}
不能。由于类型擦除,在字节码中,因此在运行时,Iterable<Whatever>
变为Iterable
。
public interface myInterface extends Iterable, Iterable { ... }
考虑到这一点,如何确定要迭代哪个类呢?
作为一种可能的解决方案,您可以为您想要的迭代创建接口。
public interface SegmentIterable{
public Iterator<Segment> segmentIterator();
}
public interface PointIterable{
public Iterator<Point> pointIterator();
}
这并不理想,但只要您想迭代的内容有限,就可以通过。
其他人说这是不可能的。他们错了。这是可能的,但可能不是你想要的。
public interface MyInterface<T extends Point & Segment> extends Iterable<T>
{
}
如果你的迭代扩展了点和段,这将有效。
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.1.5
一个类不能同时是两个接口类型的子类型,这两个接口类型是同一泛型接口的不同调用(§9.1.2),或者是一个泛型接口调用的子类型和命名同一泛型接口的原始类型,否则会发生编译时错误。
与其继承可迭代类型,不如试试这样做:
public interface MyInterface {
public Iterable<Point> asPoints() { ... }
public Iterable<Segment> asSegments() { ... }
}
当你想迭代时,只需:
for (Point p : myClass.asPoints()) {
...
}
这是一种非常常见的做法,就像在Java Collections类中看到的那样。
您还可以考虑为Point和Segment创建通用接口、超类或包装器,并将其用作泛型参数。