¿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?
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.
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()) {
...
}
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?
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.
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á.
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.
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.
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.
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