180 likes | 417 Views
Genéricos en Java. Jaime Ramírez, Ángel Lucas González DLSIIS. Facultad de Informática Universidad Politécnica de Madrid. Introducción. Java permite definir clases con variables o parámetros que representan tipos => Clases genéricas
E N D
Genéricos en Java Jaime Ramírez, Ángel Lucas González DLSIIS. Facultad de Informática Universidad Politécnica de Madrid.
Introducción • Java permite definir clases con variables o parámetros que representan tipos => Clases genéricas • Esto es posible, cuando el tipo de un dato no afecta al tratamiento que se le va a dar a ese dato. • Un mecanismo similar está disponible en lenguajes como C#, C++ o Ada.
Introducción • Aparecen en la versión 1.5. • Antes se utilizaba la clase Object como “comodín” para simular los genéricos, pero esto conllevaba: • Se podían mezclar objetos de las clases más dispares en una misma estructura contenedora de objects. • Había que realizar muy a menudo castings (conversión de Object a cualquier otra clase).
Motivación • Supongamos que en un programa necesitamos una clase ParEnteros: public class ParEnteros { private int a, b; public ParEnteros(int a, int b){ this.a = a; this.b = b; } public ParEnteros swap (){ return new ParEnteros(b, a); } }
Motivación • Pero también necesitamos un clase ParCaracteres con los mismos métodos que la anterior. • La implementación de los métodos es la misma, porque no depende del tipo del dato manipulado => abstraemos el tipo convirtiéndolo en un parámetro genérico T.
Ejemplo clase genérica Par public class Par<T> { private T a, b; public Par(T a, T b){ this.a = a; this.b = b; } public Par<T> swap (){ return new Par<T>(b, a); } }
Ejemplo clase genérica Par public class Prueba { public static void main(String[] args) { // Instanciación de la clase genérica para Integer // No se puede usar int porque no es una clase Par<Integer> p = new Par<Integer>(1,2); // Instanciación de la clase genérica para Character Par<Character> p1 = new Par<Character>('a','b'); p = p.swap(); p1 = p1.swap(); } }
Restringiendo el parámetro genérico • Supongamos que deseamos añadir a la clase Par un método max(): public T max(){ return ((a>b) ? a : b); } • Si añadimos este método sin más, obtendremos un error de compilación, ya que a y b no tienen por qué ser de un tipo comparable con >.
Restringiendo el parámetro genérico • Debemos decirle al compilador que el tipo T sólo representará tipos de valores comparables con el > o una función equivalente (compareTo). public class Par<T extends Comparable> { private T a, b; public Par(T a, T b){ this.a = a; this.b = b; } public T max(){ return ((a.compareTo(b)>0) ? a : b); } ..................
Restringiendo el parámetro genérico • En general, se puede declarar un parámetro genérico de forma que al instanciar la clase se debe proporcionar una clase A que sea subclase de otra B o implemente una cierta interfaz B: class ClaseGen<T extends B>{ ....................... } ClaseGen<A> obj; // instanciación
Restringiendo el parámetro genérico class Stats< T extends Number > { private T[] nums; Stats(T[] o) { nums = o; } double average() { double sum = 0.0; for(int i=0; i < nums.length; i++) sum += nums[i].doubleValue(); return sum / nums.length; } }
Restringiendo el parámetro genérico double w = dob.average(); System.out.println("dob average is " + w); // Esto no compila porque String no es // subclase de Number // String strs[] = { "1", "2", "3", "4", "5" }; // Stats<String> strob = // new Stats<String>(strs); // double x = strob.average(); // System.out.println("strob average is "+v); } } public class BoundsDemo { public static void main(String args[]) { Integer inums[] = { 1, 2, 3, 4, 5 }; Stats<Integer> iob = new Stats<Integer>(inums); double v = iob.average(); System.out.println("iob average is " + v); Double dnums[] = { 1.1, 2.2, 3.3, 4.4, 5.5 }; Stats<Double> dob = new Stats<Double>(dnums);
Clases genéricas como parámetros de funciones boolean sameAvg(Stats<?> ob) { if(average() == ob.average()) return true; else return false; } • Por medio del tipo Stats<?> indicamos que esta función puede recibir un objeto de cualquier instancia de la clase genérica Stats<T extends Number>
Clases genéricas como parámetros de funciones Integer inums[] = { 1, 2, 3, 4, 5 }; Stats<Integer> iob = new Stats<Integer>(inums); double v = iob.average(); System.out.println("iob average is " + v); Double dnums[] = { 1.1, 2.2, 3.3, 4.4, 5.5 }; Stats<Double> dob = new Stats<Double>(dnums); double w = dob.average(); System.out.println("dob average is " + w); System.out.print("Averages of iob and dob "); if(iob.sameAvg(dob)) System.out.println("are the same."); else System.out.println("differ.");
Herencia y genéricos • Véase el ejemplo de los apuntes de la asignatura (pags 75-79): Implementación de una clase genérica Cola.