Genéricos y polimorfismo – Blog de Whizlabs

En los dos artículos anteriores relacionados con los genéricos, aprendimos sobre el uso y los conceptos de los genéricos. En este artículo, centrémonos en el aspecto del polimorfismo y en cómo los genéricos respaldan el polimorfismo. En general, el polimorfismo se aplica al tipo base de la colección. Por ejemplo, el siguiente código crea una ArrayList que puede contener números enteros. Tenga en cuenta que en el siguiente código el tipo base es Lista y el subtipo es ArrayList (ya que ArrayList es una subclase de Lista).

Lista numberList = new ArrayList();

En el fragmento de código anterior, List y ArrayList son tipos “base” y Integer es el tipo genérico. Debido a que ArrayList es un subtipo de Lista, podemos asignar una ArrayList a una referencia de Lista. Sin embargo, lo siguiente es INCORRECTO y no funcionará.

clase Coche { }

class Audi extiende Car { } // Audi es una subclase de Car

Lista misCoches = new ArrayList(); // ¡No funciona!

El tipo anterior de uso polimórfico no está permitido y no funcionará. Porque el tipo de declaración de variable debe ser el mismo que el tipo que pasamos al tipo de objeto real. En otras palabras, como en el ejemplo anterior, si el tipo es , entonces solo podemos asignar el tipo genérico . No podemos asignar supertipo de subtipo de coche.

Sólo para resumir, las siguientes notaciones son todas INCORRECTAS.

Lista misObjetos = new ArrayList();

// INCORRECTO aunque String sea un subtipo de Objeto.

Lista algunosNúmeros = nueva ArrayList();

// INCORRECTO aunque Integer sea un subtipo de Number.

Lo siguiente es CORRECTO, considerando el hecho de que el tipo genérico es el mismo.

Lista misEmpleados = new ArrayList();

Lista misObjetos = new ArrayList();

Lista misNúmeros = new ArrayList();

El polimorfismo se aplica sólo al tipo 'base' (tipo de clase de colección) y NO al tipo genérico.

Métodos genéricos

Para comprender cómo funcionan los genéricos en el contexto de los métodos, considere la siguiente clase abstracta Empleado y dos clases concretas PermEmployee y TempEmployee para representar al empleado permanente y al empleado temporal respectivamente.

clase abstracta Empleado {

doWork vacío abstracto público();

}

clase PermEmployee extiende Empleado {

hacer trabajo vacío público () {

System.out.println(“¡Empleado permanente trabajando!”);

}

}

clase TempEmployee extiende Empleado {

hacer trabajo vacío público () {

System.out.println(“¡Empleado temporal trabajando!”);

}

}

Considerando el ejemplo de Empleado anterior, si tenemos un método que acepta una lista de empleados y realiza algún procesamiento:

clase pública ProcesadorEmpleado {

proceso público vacío Empleado (Lista Lista de empleados) {

// algún procesamiento.

}

}

Solo podemos invocar el método ProcessEmployee() con una lista de tipo genérico Empleado SOLAMENTE y NO con ningún subtipo genérico. Lo siguiente no funcionará y nos da errores de compilación.

Lista empleados = new ArrayList();

empleados.add(new PermEmployee());

procesoEmpleado(empleados); // ERROR

La razón detrás de no permitir que se pasen subtipos a un método que toma una colección de un supertipo es que existe la posibilidad de que agreguemos un objeto INCORRECTO. Dado que el compilador no tiene forma de evitar que coloquemos objetos de subtipo incorrectos en una colección de supertipos, para evitar los problemas, los diseñadores del lenguaje Java restringieron el paso de subtipos genéricos donde se espera un supertipo genérico en el momento de la compilación. Además, debido al “borrado de tipo”, la JVM no puede determinar qué objeto se ha pasado hasta el tiempo de ejecución.

Sin embargo, podemos agregar directamente los objetos de subtipo a la lista que tiene un supertipo genérico.

Entonces, si tenemos una lista de empleados como se muestra a continuación:

Lista empleados = new ArrayList();

empleados.add(new PermEmployee()); //ESTO ES VÁLIDO.

empleados.add(new TempEmployee()); //ESTO ES VÁLIDO.

Podemos agregar una instancia de un subtipo a una colección declarada con un supertipo.

Solución alterna

En algunas situaciones, es posible que tengamos que solucionar las restricciones anteriores y deberíamos poder pasar el subtipo genérico donde se espera el supertipo genérico. En tales situaciones, podemos indicarle al compilador que acepte cualquier subtipo genérico del tipo de argumento declarado prometiendo (sí ) que no pondremos nada en la colección. Hacemos esto usando la sintaxis de comodines

Cambiemos la firma de nuestro método ProcessEmployee() para satisfacer esta necesidad.

proceso público vacío Empleado (Lista Lista de empleados) {

// algún procesamiento.

}

Usando el código anterior, estamos obligando al compilador a aceptar un subtipo genérico en lugar de un supertipo genérico y tampoco debemos agregar nada a esta lista dentro del método. Si intentamos agregar algo a esta lista desde el método, nuestro código no se compilará. Somos libres de recorrer la lista e invocar métodos en cada objeto recuperado.

Otro punto a tener en cuenta es que la palabra clave 'extiende' en la expresión comodín también representa AMBAS subclases e implementaciones de interfaz. Podemos pasar subtipos genéricos que extiendan otra clase o implementen una interfaz.

Hasta ahora hemos visto cómo funciona el polimorfismo con genéricos y colecciones. En los próximos artículos, aprenderemos otro tema interesante en Java. ¡Nos vemos en el próximo artículo!

Comprenda más sobre genéricos y polimorfismo en el curso de capacitación Whizlabs OCPJP 6.

Publicaciones Similares

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *