Java Generics - Universidad de Buenos Aires

Anuncio
75-62 Técnicas de
Programación Concurrentes II
Lic. Ing. Osvaldo Clúa
2008
Facultad de Ingeniería
Universidad de Buenos Aires
Java Generics
Programación Genérica
●
Los programas se escriben en función de
tipos que se especificarán mas tarde.
FIUBA 2008
–
Permite escribir algoritmos mas generales.
–
Existen en Ada, Eiffel, Java, C#,
Visual Basic .NET y Haskell.
–
En C++ hay una facilidad parecida en precompilación conocida como Templates
75-08 Sistemas Operativos
Prof. Lic. Ing. Osvaldo Clúa
2
Generics en Java
●
●
Java puede tener Clases, tipos y Métodos
Genéricos.
–
Proveen una forma de chequear tipos en
compilación.
–
Manteniendo los programas legibles y
expresivos.
También se conoce esta propiedad como
Polimorfismo Paramétrico o de Tipos.
FIUBA 2008
75-08 Sistemas Operativos
Prof. Lic. Ing. Osvaldo Clúa
3
Motivación
●
Se quiere imprimir un arreglo sin conocer
el tipo de sus elementos.
public static <E> void printAr(E a[]){
int i=0;
for (E elem:a)
System.out.println((i++)+")="+elem);
}
public static void main(String[] args) {
Integer ia[]={10,20,30,40};
Double da[]={7.5,3.4,5.6};
String sa[]={"En","un","overo","rosao"};
printAr(ia);
printAr(da);
printAr(sa);
}
}
FIUBA 2008
75-08 Sistemas Operativos
Prof. Lic. Ing. Osvaldo Clúa
4
Ejercicios
●
¿Cómo infiere el tipo del parámetro de
printAr(...) en los llamados?
–
●
¿Puede llamarse especificando el tipo:
Gene01.printAr <String []>(...) ?
Resolver este mismo ejemplo usando:
–
Polimorfismo.
–
Sobrecarga de métodos.
FIUBA 2008
75-08 Sistemas Operativos
Prof. Lic. Ing. Osvaldo Clúa
5
Un Ejemplo
●
Se desarrollará una pila y una lista usando
Generics.
–
El layout del código se optimizó para que
cupiera en las slides.
●
●
Se quitaron líneas en blanco y comentarios javadoc
que son obligatorios en las entregas.
La pila y la lista funcionan sobre dos clases
base ejemplo: Fracción y java.lang.Integer
FIUBA 2008
75-08 Sistemas Operativos
Prof. Lic. Ing. Osvaldo Clúa
6
La clase base
Fracción (1)
public class Fraccion {
private int num;
private int den;
public Fraccion(){num=1; den=1;}
public Fraccion(Fraccion f){num=f.num; den=f.den;}
public Fraccion(int n,int d) {
setNum(n); setDen(d);
normalizar();
}
public int getNum() { return num; }
public void setNum(int num) {
this.num = num;
normalizar(); }
public int getDen() { return den; }
FIUBA 2008
75-08 Sistemas Operativos
Prof. Lic. Ing. Osvaldo Clúa
7
La clase base
Fracción (2)
public void setDen(int den) {
this.den = den;
normalizar();
}
private void normalizar(){
int mcd=Math.abs(mcd(num,den));
num=num/mcd;
den=den/mcd;
}
static private int mcd(int x,int y){
if (y==0)return x;
else return mcd(y, x%y);
}
public String toString(){
return num+"/"+den;
}
}
FIUBA 2008
75-08 Sistemas Operativos
Prof. Lic. Ing. Osvaldo Clúa
8
La Pila Genérica
import Fraccion.Fraccion;
public class PilaGen<E> {
class NodoGe {
E dato;
NodoGe sig;
NodoGe(E o, NodoGe s) {
dato = o;
sig = s; }
}
NodoGe top;
public PilaGen() {
top = null; }
public void push(E o) { top = new NodoGe(o, top); }
public E pop() { E x = top.dato; top = top.sig; return x; }
public boolean isEmpty() { return top == null;}
FIUBA 2008
75-08 Sistemas Operativos
Prof. Lic. Ing. Osvaldo Clúa
9
Prueba de la Pila Genérica
i public static void main(String[] args) {
PilaGen<Fraccion> pila = new PilaGen<Fraccion>();
PilaGen<Fraccion> pila1 = new PilaGen<Fraccion>();
// error al tratar de infiltrar un Integer, detectado en compilacion
// pila.push (new Integer(3));
pila.push(new Fraccion(7, 3));
pila.push(new Fraccion(4, 5));
pila.push(new Fraccion(3, 4));
//saca de pila y pone en pila1
while (!pila.isEmpty()) {
Fraccion o = pila.pop(); System.out.println("retirado " + o);
pila1.push(o);
}
//saca de pila1 y accede al denominador
while (!pila1.isEmpty()) {
System.out.println("Denominador " + (pila1.pop()).getDen());
}
}
}
FIUBA 2008
75-08 Sistemas Operativos
Prof. Lic. Ing. Osvaldo Clúa
10
Ejercicios
●
Hacer un programa similar usando
polimorfismo.
–
Todos son descendientes de Object.
–
¿Qué pasa con el error al “infiltrar” un
Integer?
FIUBA 2008
75-08 Sistemas Operativos
Prof. Lic. Ing. Osvaldo Clúa
11
La Lista Genérica
●
FIUBA 2008
Es un código parecido
con los métodos de la
figura.
–
También usa una clase
interna Nodo.
–
Los métodos privados
se usan para
recursividad.
75-08 Sistemas Operativos
Prof. Lic. Ing. Osvaldo Clúa
12
Un Sort genérico
public class Utiles{
static <E> void sortSel
(ListaGen <E> l, Comparator <E> c)
{
for (int i=0;i<=l.size();i++){
E uno=l.datAt(i);
for (int j=i+1;j<l.size();j++){
E dos=l.datAt(j);
if (c.compare(uno,dos)>0){
l.ponerEn(j,uno);
l.ponerEn(i,dos);
uno=l.datAt(i);
}
}
}
}
}
FIUBA 2008
Es un sort por selección
en una class de utilitarios.
●
Recibe una ListaGen y un
comparador.
●
75-08 Sistemas Operativos
Prof. Lic. Ing. Osvaldo Clúa
●
●
Que devuelve (-1,0,1)
Como el pedido por la
interface
java.util.Comparator
13
Prueba de la Lista Genérica
import Integer.IntCmp;
import Fraccion.FracCmp;
import Fraccion.Fraccion;
public class PruLG {
public static void main(String[] args) {
ListaGen<Integer> li =
new ListaGen<Integer>();
li.agregar(13);
li.agregar(54);
li.agregar(2);
li.agregar(23);
li.print();
Utiles.sortSel(li, new IntCmp());
li.print();
FIUBA 2008
ListaGen<Fraccion> lf =
new ListaGen<Fraccion>();
lf.agregar(new Fraccion(2, 4));
lf.agregar(new Fraccion(1, 3));
lf.agregar(new Fraccion(1, 16));
lf.agregar(new Fraccion(5, 8));
lf.agregar(new Fraccion(7, 17));
lf.print();
Utiles.sortSel(lf, new FracCmp());
lf.print();
}
}
Los Comparator está en clases
apartes (FracCmp e IntCmp)
75-08 Sistemas Operativos
Prof. Lic. Ing. Osvaldo Clúa
14
Usando Clases anónimas
●
Para las llamadas al sort podría usarse
Utiles.sortSel(li, new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
return o1 – o2;
}
});
Utiles.sortSel(lf, new Comparator<Fraccion>() {
public int compare(Fraccion o1, Fraccion o2) {
return (int) Math.signum(((double) o1.getNum() / (double) (o1.getDen())) ((double) o2.getNum() / (double) (o2.getDen())));
}
});
FIUBA 2008
75-08 Sistemas Operativos
Prof. Lic. Ing. Osvaldo Clúa
15
Wildcard type (?)
●
Se usa para imponer alguna restricción en
los tipos usados como argumentos.
–
<? extends Base > significa que admite
cualquier tipo que extienda a la clase Base.
–
<? super Base > significa que admite
cualquier tipo que sea supertipo de la clase
Base.
–
<?> significa que admite cualquier tipo (sin
nombrarlo).
FIUBA 2008
75-08 Sistemas Operativos
Prof. Lic. Ing. Osvaldo Clúa
16
Type erasure
●
●
En compilación se verifican los tipos de los
parámetros y argumentos Generics.
–
Después se pierde toda información sobre el
tipo.
–
Este procedimiento se llama type erasure.
Hay una sola copia del código de la
estructura genérica, compartido por todas
sus instancias
FIUBA 2008
75-08 Sistemas Operativos
Prof. Lic. Ing. Osvaldo Clúa
17
¿Cuál es el tipo?
public static void main(String[] args) {
ListaGen<Integer> li = new ListaGen<Integer>();
ListaGen<Float> lf = new ListaGen<Float>();
if (li.getClass() == lf.getClass()) {
System.out.println("Iguales"); }
else {
System.out.println("Distintas"); }
System.out.println("El tipo de lf es: "+lf.getClass().getName());
}
●
Li y lf son listas de distintos tipos.
–
●
Esta información se pierde en ejecución.
Las estructuras genéricas no pueden ser
static.
FIUBA 2008
75-08 Sistemas Operativos
Prof. Lic. Ing. Osvaldo Clúa
18
Descargar