Подтвердить что ты не робот

Как создать интерфейс Java, который расширяет Iterable с помощью двух разных типов?

В идеале это будет выглядеть так (контекст не имеет значения):

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

Но это не разрешено в Java. Как я могу достичь такого поведения?

4b9b3361

Ответ 1

К сожалению, вы не можете. В Java у вас не может быть двух методов со следующими сигнатурами:

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

в одном классе или интерфейсе.

Ответ 2

Как и раньше, это невозможно. Лучше использовать делегирование вместо множественной реализации следующим образом:

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

Итак, вы можете использовать итерацию для:

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

Ответ 3

Вы не можете. Из-за стирания типа, в байтекоде и, следовательно, во время выполнения Iterable<Whatever> становится Iterable.

Итак, во время выполнения прототип вашего класса будет:

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

Учитывая, что, как вы определяете, какой класс должен был повторяться?

Ответ 4

В качестве возможного решения можно создать интерфейсы для желаемых итераций.

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

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

Он не идеален, но будет проходимым, если у вас есть ограниченное количество вещей, которые вы хотели перебрать.

Ответ 5

Другие говорили, что это невозможно. Они не правы. Возможно, но, вероятно, не то, что вы хотите.
public interface MyInterface<T extends Point & Segment> extends Iterable<T>
{
}

Если то, что вы итерируете, расширяет как точку, так и сегмент, это будет работать. В противном случае Type Erasure означает, что это не сработает.

Ответ 6

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

В то же время класс не может быть подтипом двух типов интерфейса, которые являются разными вызовами одного и того же общего интерфейса (§9.1.2) или подтипом вызова основного интерфейса и именного типа, такой же общий интерфейс или ошибка времени компиляции.

Ответ 7

Вместо наследования от повторяющихся типов попробуйте что-то вроде этого:

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

Затем, когда вы хотите выполнить итерацию, это просто вопрос:

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

Это довольно распространенная практика, как видно из класса Java Collections.

Ответ 8

Вы также можете рассмотреть возможность создания общего интерфейса, суперкласса или оболочки для Point и Segment и использовать его как общий параметр.