21

理想情况下,它看起来像这样(上下文无关紧要):

public interface myInterface extends Iterable<Point>, Iterable<Segment> { ... }

但这在 Java 中是不允许的。我怎样才能实现这种行为?

4

8 回答 8

20

不幸的是你不能。在 Java 中,您不能有两个具有以下签名的方法:

Iterator<Point> iterator();
Iterator<Segment> iterator();

在一个类或接口中。

于 2013-06-06T19:04:04.023 回答
18

正如其他人之前所说,这是不可能的。更好地使用委托而不是像这样的多个实现:

public interface MyInterface {
  Iterable<Point> points();
  Iterable<Segment> segments();
}

因此,您可以使用for进行迭代:

MyInterface my = ...;
for (Point p : my.points()) {
  ...
}
for (Segment s : my.segments()) {
  ...
}
于 2013-06-06T19:17:47.127 回答
9

你不能。由于类型擦除,在字节码中,因此在运行时,Iterable<Whatever>变成Iterable.

因此,在运行时,您的类的原型将是:

public interface myInterface extends Iterable, Iterable { ... }

考虑到这一点,您如何确定要迭代的类?

于 2013-06-06T19:05:33.290 回答
5

作为一种可能的解决方法,您可以为所需的迭代创建接口。

public interface SegmentIterable{
    public Iterator<Segment> segmentIterator();
}

public interface PointIterable{
    public Iterator<Point> pointIterator();
}

这并不理想,但只要您想要迭代的东西数量有限,就可以通过。

于 2013-06-06T19:06:08.127 回答
3

其他人说这是不可能的。他们错了。这是可能的,但可能不是你想要的。

public interface MyInterface<T extends Point & Segment> extends Iterable<T>
{
}

如果您正在迭代的内容同时扩展了点和段,这将起作用。否则类型擦除意味着这将不起作用。

于 2013-06-06T20:23:41.780 回答
2

http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.1.5

一个类不能同时是两个接口类型的子类型,这两种接口类型是同一泛型接口的不同调用(第 9.1.2 节),或者是泛型接口调用的子类型和命名同一泛型接口的原始类型,或发生编译时错误。

于 2013-06-06T20:07:10.493 回答
2

而不是从可迭代类型继承,尝试这样的事情:

public interface MyInterface {
    public Iterable<Point> asPoints() { ... }
    public Iterable<Segment> asSegments() { ... }
}

然后,当您想要迭代时,只需:

for (Point p : myClass.asPoints()) {
    ...
}

这是一种非常常见的做法,如 Java Collections 类中所见。

于 2013-06-06T21:07:55.340 回答
0

您还可以考虑为 Point 和 Segment 创建通用接口、超类或包装器,并将其用作通用参数。

于 2013-06-06T19:10:39.627 回答