В идеале это будет выглядеть так (контекст не имеет значения):
public interface myInterface extends Iterable<Point>, Iterable<Segment> { ... }
Но это не разрешено в Java. Как я могу достичь такого поведения?
В идеале это будет выглядеть так (контекст не имеет значения):
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>
{
}
Если то, что вы итерируете, расширяет как точку, так и сегмент, это будет работать. В противном случае Type Erasure означает, что это не сработает.
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 и использовать его как общий параметр.