如何使用两种不同的泛型类型创建扩展Iterable的Java接口?

时间:2013-06-06 18:59:20

标签: java generics interface

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

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

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

8 个答案:

答案 0 :(得分:19)

很遗憾你不能。在Java中,您不能拥有以下签名的两种方法:

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

在一个类或接口中。

答案 1 :(得分:16)

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

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

所以你可以使用迭代

MyInterface my = ...;
for (Point p : my.points()) {
  ...
}
for (Segment s : my.segments()) {
  ...
}

答案 2 :(得分:9)

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

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

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

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

答案 3 :(得分:5)

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

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

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

这不是理想的,但只要您想要迭代的事物数量有限,就可以通过。

答案 4 :(得分:3)

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

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

如果您正在迭代的内容扩展了点和段,这将起作用。否则Type Erasure意味着这不会起作用。

答案 5 :(得分:2)

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

  

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

答案 6 :(得分:2)

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

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

然后当你想要迭代时,它只是一个问题:

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

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

答案 7 :(得分:0)

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