¿Cómo hacer una interfaz Java que se extiende Iterable con dos tipos genéricos diferentes?


Idealmente, se vería así (el contexto no importa):

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

Pero esto no está permitido en Java. ¿Cómo puedo lograr este comportamiento?

Author: Kirk Woll, 2013-06-06

8 answers

Desafortunadamente no puedes. En Java no se pueden tener dos métodos con las siguientes firmas:

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

En una clase o interfaz.

 19
Author: Grzegorz Żur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-06 19:04:04

Como otros dijeron antes, esto es imposible. Mejor uso de delegación en lugar de implementación múltiple como esta:

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

Así que puedes iterar usando para :

MyInterface my = ...;
for (Point p : my.points()) {
  ...
}
for (Segment s : my.segments()) {
  ...
}
 16
Author: Arne Burmeister,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-09 10:21:24

No puedes. Debido al tipo erasure, en el bytecode, y por lo tanto en tiempo de ejecución, Iterable<Whatever> se convierte en Iterable.

Así que, en tiempo de ejecución, el prototipo de su clase sería:

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

Teniendo en cuenta eso, ¿cómo se determina qué clase estaba destinada a ser iterada?

 9
Author: fge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-06 19:05:33

Como posible solución, puede crear interfaces para las iteraciones que desee.

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

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

No es ideal, pero sería aceptable siempre y cuando tuvieras un número limitado de cosas que quisieras repetir.

 5
Author: greedybuddha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-06 19:07:14

Otros han dicho que es imposible. Están equivocados. Es posible, pero probablemente no lo que quieres.

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

Si lo que está iterando extiende tanto el punto como el segmento, esto funcionará. De lo contrario, el tipo Borrado significa que esto no funcionará.

 3
Author: emory,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-06 20:33:13

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

Una clase puede no ser al mismo tiempo un subtipo de dos tipos de interfaz que son invocaciones diferentes de la misma interfaz genérica (§9.1.2), o un subtipo de una invocación de una interfaz genérica y un tipo raw que nombra esa misma interfaz genérica, o se produce un error en tiempo de compilación.

 2
Author: ZhongYu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-06 20:07:10

En lugar de heredar de los tipos iterables, intente algo como esto:

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

Entonces, cuando se quiere iterar, es simplemente una cuestión de:

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

Esta es una práctica bastante común, como se ve en la clase Java Collections.

 2
Author: fluffy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-06 21:07:55

También puede considerar la creación de interfaz común, superclase o envoltura para el Punto y el Segmento y usarlo como un parámetro genérico.

 0
Author: Marcin Jedynak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-06 19:10:39