理想情况下,它看起来像这样(上下文无关紧要):
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();
}
因此,您可以使用for进行迭代:
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 创建通用接口、超类或包装器,并将其用作通用参数。