11 de diciembre de 2020

Wildcards

Para terminar esta introducción a genéricos nos faltaría ver las wildcards que nos permiten poder definir un tipo variable usando como identificador del parámetro el carácter "?".

Es muy habitual verlo en la firma de los métodos para admitir cualquier Collection que admita un tipo de elemento o cualquiera de los subtipos de ese elemento, ya que Collection<Vehiculo> no es asignable a Collection<Coche>. En este ejemplo vamos a definir un método que admita esos dos tipos de colecciones:

private static void imprimirFlota(Collection<? extends Vehiculo> vehiculos) {
    vehiculos.forEach(System.out::println);
}

Su utilidad la vemos a continuación:

Collection coleccionRaw = Arrays.asList(new Coche(), new CocheProducto("", "", 10000.0f));
Collection<Vehiculo> vehiculos = coleccionRaw;
//  Collection<Coche> coches = vehiculos; // Error
imprimirFlota(vehiculos);
Collection<Coche> coches = coleccionRaw;
imprimirFlota(coches);
NOTA: Puede parecer que lo mejor es no definir el tipo ya que "no tiene el problema" que tenemos si lo definimos. Eclipse nos dará un warning tanto al declarar la variable (dirá que debemos declararlo) como al asignarla (nos advierte que no se puede checkear la seguridad de tipo). En resumen, hay que definirlo por seguridad de nuestro código en tiempo de compilación y porque de lo contrario no tendremos acceso a los miembros más allá de los pertenecientes a Object.

Sin tener más conocimiento sobre genéricos no recomiendo usar las wildcards en otro contexto ya que lo más normal es que tengamos muchos problemas. No obstante se puede usar como guía estas guidelines.

Hay más conceptos sobre genéricos, de hecho hay libros enteros sólo sobre este tema con términos como type erasure, pero que no se van a ver en esta introducción de fundamentos, aunque hay que tenerlos presentes pues no conocerlos puede darnos quebraderos de cabeza (lo típico que te dice que no se puede implementar dos veces la misma interface; prueba a implementar Comparable<Coche> en la clase Coche y te encontrarás con el mensaje: "The interface Comparable cannot be implemented more than once with different arguments: Comparable<Vehiculo> and Comparable<Coche>" que lo causa el type erasure).

Genéricos (desde Java 5) al igual que streams o lambdas (desde Java 8) son grandes avances pero quedan fuera del alcance que se pretende en esta parte de fundamentos. Puedes encontrar más tutoriales en la página oficial de Oracle.

No hay comentarios:

Publicar un comentario

Compárteme

Entradas populares