Foro sobre Java SE > Generics
¿Cómo tienes definidas las clases Animal y Dog?
Hola,
Clase Animal:
public class Animal<T> {
}
Clase Dog:
public class Dog<T> extends Animal<T> {
}
¿Por qué no las defines asi?
public class Animal {
}
public class Dog extends Animal {
}
Porque estoy trabajando y tratando de entender como funciona generics.
Bien, pero no es necesario complicar innecesariamente las declaraciones de las clases con genéricos, para aprender cómo funcionan.
El uso de un "wildcard" como <T> en la declaración de una clase, solamente debe hacerse cuando es absolutamente imprescindible, es decir, cuando la clase no puede usarse correctamente sin él.
Es habitual que algunos métodos de una clase usen parámetros con "wildcards" genéricos, sin que la clase en sí los declare.
En genéricos, como en todo lo demás, si lo sencillo funciona correctamente, mejor no complicarlo sin necesidad.
choces es unos de mis maestros. amén a tu post... TEngo un compañero que en mi proyecto me esta declarando una clase producto algo así:
class UnidadMayorista extends ProductoBase<t extends ProductoBase < ? extends Producto>>{...}
Algo así... Los genericos al principio parecen complicados, pero no lo son en realidad.
La idea es esta:
un <T> es algo... No importa que, que lo usas como "wilcard" para hacer cosas que de otra manera no podrías...
por ejemplo:
class Controlador <T> {
public T getInstance(){}
}
class UnControlador <UnControlador> extends Controller{
}
Lo anterior me permite no tener la necesidad de castear lo que devuelve el metodo getInstance().
Pero los genericos tienen mas poder. Es cuestion de ir pensando en donde es necesario.... Solo en donde es necesario porque suelen complicar demasiado todo y hace un codigo poco legible...
Tu problema creo que es un tema de generics + colecciones.. que los tipados suelen no seguir una lógica coherente en estos casos... pero no me acuerdo bien porque
Tu método recibe como parámetro un List<Animal<? extends Animal>>, es decir, un listado concreto de animales de un tipo desconocido de animales (usas un wildcard como argumento).
A este método le mandas un listado concreto de animales de tipo Animal y un listado concreto de animales de tipo Dog, y ninguno de estos es igual o son compatibles con lo que espera tu método como parámetro.
Lo que debes hacer, es convertir el parámetro que recibe tu método en un supertipo de los argumentos que estás enviando, y eso lo haces así con List<? extends Animal<? extends Animal>>, de esta forma tu parámetro ya no es un listado concreto de animales, sino que representa un listado de una familia de animales.
Te recomiendo que leas un poco sobre multi level wildcards.
Saludos.
Hola,
Tengo un método como el siguiente:
public static void leerCajas(List<Animal<? extends Animal>> animales) { ... }
Mediante el siguiente código pruebo mi método:
List<Animal<Animal>> animales = new ArrayList<Animal<Animal>>();
List<Animal<Dog>> animales2 = new ArrayList<Animal<Dog>>();
leerCajas(animales); //compile error
leerCajas(animales2); //compile error
Y sorprendentemente y contra toda mi lógica, me muestra un error como el siguiente:
Te method leerCajas(List<Animal<? extends Animal>>) is not applicable for the arguments (List<Animal<Animal>>)
Para evitar este error en tiempo de compilación he modificado el método leerCajas de la siguiente forma:
public static void leerCajas(List<? extends Animal<? extends Animal>> animales) { ... }
Y de esta forma va perfecto.
Pero a ciencia cierta, no entiendo por qué debo hacerlo de esa forma, me parece que el método en su forma original está perfecto y que no hay nada malo en la forma como estoy pasando los valores al método.
Sin embargo, parece que no termino de entender esto del generics.
Me podrían ayudar a entender por qué mi código original da error?
Muchas gracias desde ya.