简体   繁体   中英

How to make a Java interface that extends Iterable with two different generic types?

Ideally, it would look like this (the context doesn't matter):

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

But this is not allowed in Java. How can I achieve this behaviour?

Unfortunately you cannot . In Java you cannot have two methods with following signatures:

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

in one class or interface.

As other said before, this is impossible. Better use delegation instead of multiple implementation like this:

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

So you can iterate using for :

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

You cannot. Due to type erasure, in the bytecode, and therefore at run time, Iterable<Whatever> becomes Iterable .

So, at run time, your class' prototype would be:

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

Considering that, how do you determine what class was meant to be iterated over?

As a possible workaround, you could create interfaces for the iterations you want.

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

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

It's not ideal, but would be passable as long as you had a limited number of things you wanted to iterate over.

Others have said it is impossible. They are wrong. It is possible, but probably not what you want.

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

If what you are iterating extends both point and segment this will work. Otherwise Type Erasure means this won't work.

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

A class may not at the same time be a subtype of two interface types which are different invocations of the same generic interface (§9.1.2), or a subtype of an invocation of a generic interface and a raw type naming that same generic interface, or a compile-time error occurs.

Instead of inheriting from the iterable types, try something like this:

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

Then when you want to iterate, it's simply a matter of:

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

This is a pretty common practice, as seen in the Java Collections class.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM