Vous êtes sur la page 1sur 16

Tema 1 (Parte 3)

Tipos parametrizados

J. Gutirrez

Departament d'Informtica
Universitat de Valncia

Programacin (GIET).
Curso 12/13

J. Gutirrez, Tema 1 (Parte 3)

Curso 12/13

1/32

Curso 12/13

2/32

ndice

Objetivos

Motivacin

Tipos parametrizados

Exigir requisitos sobre el parmetro del tipo

Algunos tipos del Collections Framework


Recorrido de colecciones

J. Gutirrez, Tema 1 (Parte 3)

Objetivos

ndice

Objetivos

Motivacin

Tipos parametrizados

Exigir requisitos sobre el parmetro del tipo

Algunos tipos del Collections Framework

J. Gutirrez, Tema 1 (Parte 3)

Curso 12/13

3/32

Objetivos

Objetivos I

Declarar y usar tipos parametrizados.

Describir las ventajas de usar tipos parametrizados.

Imponer requisitos sobre el parmetro del tipo: <T extends


Interface>.

Declarar y usar interfaces parametrizadas.

Usar los contenedores parametrizados (del


ofrece Java

J. Gutirrez, Tema 1 (Parte 3)

Collections Framework) que

Curso 12/13

4/32

Objetivos

Objetivos II

Usar los mecanismos que ofrece Java para facilitar el recorrido de las
colecciones.

J. Gutirrez, Tema 1 (Parte 3)

Curso 12/13

5/32

Curso 12/13

6/32

Motivacin

ndice

Objetivos

Motivacin

Tipos parametrizados

Exigir requisitos sobre el parmetro del tipo

Algunos tipos del Collections Framework

J. Gutirrez, Tema 1 (Parte 3)

Motivacin

Objetivo

Crear contenedores de datos que puedan contener cualquier tipo de dato y


que permitan detectar errores en su uso en tiempo de compilacin.
En la parte 2 del tema 1 hemos visto que puedo referenciar cualquier objeto
con una referencia del tipo Object
Por tanto un modo trivial de hacer un contenedor sera haciendo uso de
esta referencia. Por ejemplo:
public class Contenedor {
private Object el ;

public setElement ( Object o){


el = o;
}
public Object getElement () {
return el ;
}

J. Gutirrez, Tema 1 (Parte 3)

Curso 12/13

7/32

Motivacin

El cdigo anterior es correcto y se puede usar del siguiente modo:


Contenedor c = new Contenedor () ;
String s = `` Hola mundo '';
c. setElement (s);
Object o = c . getElement () ;

J. Gutirrez, Tema 1 (Parte 3)

Curso 12/13

8/32

Motivacin

Pero:
1

Es incmodo de usar ya que al recuperarlo tengo una referencia del


tipo Object, por lo que ser necesario realizar un downcasting
explcito para acceder a la funcionalidad del objeto almacenado:
System . out . println ((( String )c . getElement () ). indexOf () );

Puede dar lugar a errores en tiempo de ejecucin al insertar objetos de


un tipo y al recuperarlos intentar referenciarlos con referencias no
compatibles:
Contenedor c = new Contenedor () ;
String s = `` Hola mundo '';
c. setElement (s);
Integer entero = ( Integer )c. getElement () ;

Ese error no es detectado en tiempo de compilacin y el error se


obtiene al ejecutar ya que estamos intentando referenciar un objeto de
tipo String con una referencia del tipo Integer.
Ofrece algn mecanismo el lenguaje para solucionar este inconveniente y
el probable error?
J. Gutirrez, Tema 1 (Parte 3)
Curso 12/13
9/32
Tipos parametrizados

ndice

Objetivos

Motivacin

Tipos parametrizados

Exigir requisitos sobre el parmetro del tipo

Algunos tipos del Collections Framework

J. Gutirrez, Tema 1 (Parte 3)

Curso 12/13

10/32

Tipos parametrizados

Declaracin de tipos parametrizados

Solucin: Tipos parametrizados (tambin llamados plantillas o

templates)

Se declara un tipo de dato que tiene un parmetro libre. Ese parmetro


representa a un tipo E que por ahora es desconocido.
Ese parmetro libre ser jado en el momento de creacin del objeto.
public class Contenedor <E >{
private E el ;

public void setElement (E e){


el = e;
}
public E getElement () {
return el ;
}

El cdigo se escribe en funcin de un tipo que hemos denotado como E que


de momento desconocemos.
J. Gutirrez, Tema 1 (Parte 3)

Curso 12/13

11/32

Tipos parametrizados

Ejemplos de uso del tipo parametrizado

El parmetro de tipo se especica cuando se crea el objeto:


class Prueba {
public static void main ( String [] args ) {
Contenedor < String > c = new Contenedor < String >() ;
c. setElement (`` Esto es una cadena '');
int val = c. getElement () . indexOf ( 'n ') ;
}
}

En este cdigo vemos que se ha creado una instancia del tipo Contenedor
y el parmetro del tipo es de tipo String.
Por tanto, para esta instancia, < E > se sustituye por String.
Vemos que el inconveniente de realizar el

J. Gutirrez, Tema 1 (Parte 3)

downcasting ha desaparecido.

Curso 12/13

12/32

Tipos parametrizados

Adems, ahora el compilador tiene informacin sobre lo que contiene y por


tanto puede realizar la comprobacin:
class Prueba {
public static void main ( String [] args ) {
Contenedor < String > c = new Contenedor < String >() ;

// Esta sentencia provoca un error de compilacin


// ya que c solo puede almacenar objetos del
// tipo {\ tt String }
c. setElement ( new Integer (9) );

J. Gutirrez, Tema 1 (Parte 3)

Curso 12/13

13/32

Curso 12/13

14/32

Exigir requisitos sobre el parmetro del tipo

ndice

Objetivos

Motivacin

Tipos parametrizados

Exigir requisitos sobre el parmetro del tipo

Algunos tipos del Collections Framework

J. Gutirrez, Tema 1 (Parte 3)

Exigir requisitos sobre el parmetro del tipo

En la parte 2 del tema vimos que se podan desarrollar algoritmos genricos


y que las operaciones sobre el tipo se pueden exigir mediante una interfaz.
En el caso de los tipos parametrizados tambin podemos exigir requisitos
sobre el parmetro del tipo.
El motivo es que para el correcto funcionamiento del contenedor puede ser
necesario que el tipo posea alguna operacin.

J. Gutirrez, Tema 1 (Parte 3)

Curso 12/13

15/32

Exigir requisitos sobre el parmetro del tipo

Por ejemplo supongamos que queremos realizar un contenedor que


mantenga ordenados los datos.
Est claro que para mantener los datos ordenados necesitamos compararlos:
class ContenedorOrdenado <T >{
private T [] datos ;
private int numEl ;
public void inserta (T d){
int cont = 0;
while (( cont < numEl ) & ( datos [i ] compara con
cont ++;
...
}

d))

public E getMenor () {
return datos [0];
}
...

Se necesita que los datos se puedan comparar, pero cmo se exige?.


El argumento d es de tipo T. Y con referencias del tipo T no podemos
enviar ningn mensaje al objeto.
J. Gutirrez, Tema 1 (Parte 3)

Curso 12/13

16/32

Exigir requisitos sobre el parmetro del tipo

Aproximacin 1

Declaramos una interfaz con la operacin que necesitamos:


public interface EsComparable {
public int compara ( EsComparable c);
}

y exigimos que el tipo del parmetro implemente a esa interfaz:


class ContenedorOrdenado <T extends EsComparable >{
private T [] datos ;
private int numEl ;

public void inserta (T d){


int cont = 0;
while (( cont < numEl ) & ( datos [i ]. compara ( d) <0) )
cont ++;
...
}
...

J. Gutirrez, Tema 1 (Parte 3)

Curso 12/13

17/32

Exigir requisitos sobre el parmetro del tipo

Las clases cuyas instancias queremos almacenar en este contenedor deben


implementar a la interfaz.
Ejemplo 1:
class Empleado implements EsComparable {
...
public int compara ( EsComparable c){
// Comparacin de este empleado con el que pasan
// Hay que hacer un cast de EsComparable a Empleado
Empleado e = ( Empleado ) c;
...
}
}

Puesto que Empleado es (y lo es porque implementa a) Comparable


entonces cumple con el requisito exigido por ContenedorOrdenado y por
tanto el siguiente cdigo es correcto:
...
ContenedorOrdenado < Empleado > co = new ContenedorOrdenado < Empleado >() ;
...

J. Gutirrez, Tema 1 (Parte 3)

Curso 12/13

18/32

Exigir requisitos sobre el parmetro del tipo

Ejemplo 2:
class Figura implements EsComparable {
...
public int compara ( EsComparable c){
// Comparacin de esta figura con la que pasan
// Hay que hacer un cast de EsComparable a Figura
Figura f = ( Figura ) c;
...
}
}

Puesto que Figura es (y lo es porque implementa a) Comparable entonces


cumple con el requisito exigido por ContenedorOrdenado y por tanto el
siguiente cdigo es correcto:
...
ContenedorOrdenado < Figura > co = new ContenedorOrdenado < Figura >() ;
...

J. Gutirrez, Tema 1 (Parte 3)

Curso 12/13

19/32

Exigir requisitos sobre el parmetro del tipo

Aproximacin 2: parametrizar la interfaz

Vemos que en el cdigo anterior, en el mtodo que tenemos que realizar


por implementar a la interfaz, hay que realizar un downcast. Esto se puede
evitar haciendo que la interfaz sea parametrizada:
public interface EsComparable <T >{
public int compara (T t );
}
class ContenedorOrdenado <T extends EsComparable <T > >{
private T [] datos ;
private int numEl ;

public void inserta (T d){


int cont = 0;
while (( cont < numEl ) & ( datos [i ]. compara ( d) ==0) )
cont ++;
...
}

J. Gutirrez, Tema 1 (Parte 3)

Curso 12/13

20/32

Exigir requisitos sobre el parmetro del tipo

La clases cuyas instancias quiero almacenar en este contenedor deben


implementar a la interfaz.
Ejemplo 1:
class Empleado implements EsComparable < Empleado >{
...
public int compara ( Empleado e){
// Comparacin de este empleado con el que pasan
}
}

Ejemplo 2:
class Figura implements EsComparable < Figura >{
...
public int compara ( Figura e) {
// Comparacin de esta figura con la que pasan
}
}

La ventaja de esta segunda aproximacin es que nos evitamos el downcast


en la implementacin de los mtodos de la interfaz. Comparar este cdigo
con el de las diapositivas 17 y 18.
J. Gutirrez, Tema 1 (Parte 3)

Algunos tipos del

Curso 12/13

21/32

Curso 12/13

22/32

Collections Framework

ndice

Objetivos

Motivacin

Tipos parametrizados

Exigir requisitos sobre el parmetro del tipo

Algunos tipos del Collections Framework

J. Gutirrez, Tema 1 (Parte 3)

Algunos tipos del

Collections Framework

El Collections Framework es una biblioteca de tipos que dene


contenedores de datos y algoritmos (ordenacin y bsqueda).
Esta biblioteca de tipos est organizada del siguiente modo:

Interfaces
Implementan

Clases Abstractas
Extienden

Clases

J. Gutirrez, Tema 1 (Parte 3)

Algunos tipos del

Curso 12/13

23/32

Collections Framework

Algunas interfaces del

Collections Framework

<E>
Dene los mtodos que deben tener todas las clases (es la interfaz base)
Collection

<E>
Las colecciones ofrecen un mtodo para obtener un iterador. El iterador
permite recorrer los elementos de la coleccin.
Iterator

<E> extends Collection<E>


Representa a un conjunto (no puede almacenar elementos repetidos).
Set

J. Gutirrez, Tema 1 (Parte 3)

Curso 12/13

24/32

Algunos tipos del

Collections Framework

Algunas interfaces del

Collections Framework

<E> extends Set<E>


Representa a un conjunto donde los elementos estn ordenados.
SortedSet

<E> extends SortedSet<E>


Ofrece operaciones adicionales: obtener los mayores a uno dado, ...
NavigableSet

<E> extends Collection<E>


Grupo de elementos (puede haber elementos repetidos).
List

<K,V>
Representa a un objeto que almacena pares del tipo (clave,valor) y el
acceso al valor se realiza a travs de la clave.
Map

J. Gutirrez, Tema 1 (Parte 3)

Algunos tipos del

Curso 12/13

25/32

Collections Framework

Algunas clases abstractas del

Collections Framework

<E> implements Collection<E>


Esqueleto de implementacin de la interfaz Collection.
AbstractCollection

<E> extends AbstractCollection<E>


Esqueleto de implementacin para representar una lista de elementos con
acceso aleatorio
AbstractList

<E> extends AbstractList<E>


Esqueleto de implementacin para representar una lista de elementos con
acceso secuencial (para llegar al elemento i hay que pasar por los i 1
anteriores).
AbstractSequentialList

J. Gutirrez, Tema 1 (Parte 3)

Curso 12/13

26/32

Algunos tipos del

<E>

AbstractSet

Collections Framework

<E>

extends AbstractCollection

implements

<E>
Esqueleto de implementacin de la interfaz Set.

Set

<K,V> implements Map<K,V>


Esqueleto de implementacin de la interfaz Map.
AbstractMap

J. Gutirrez, Tema 1 (Parte 3)

Algunos tipos del

<E>

27/32

Collections Framework

Algunas clases del


LinkedList

Curso 12/13

Collections Framework

extends AbstractSequentialList

<E>

implements

<E> ...
Lista enlazada con acceso secuencial, por tanto si la aplicacin requiere un
almacn en el que se acceda a diferentes posiciones, este no ser un buen
almacn. Sin embargo, puede ser un candidato si simplemente queremos
recorrer todos los elementos mediante un iterador.
List

<E> extends AbstractList<i>mplements List<E> ...


En este caso el acceso es aleatorio. Utiliza un array para almacenar los
datos y puede crecer de tamao.
Vector

<E> extends
Similar a la anterior.
ArrayList

AbstractList

J. Gutirrez, Tema 1 (Parte 3)

<i>mplements

List

Curso 12/13

<E>

...

28/32

Algunos tipos del

Collections Framework

Collections Framework

Algunas clases del

TreeSet<E> extends AbstractSet

<E>

<E>

implements NavigableSet

...

Implementacin del conjunto mediante un rbol binario donde las


operaciones insertar, borrar y comprobar si tiene un elemento tienen un
coste de O (logn.

<K,V> extends AbstractMap<K,V> implements


Map<K,V>,...
Las operaciones insertar y obtener tienen un coste constante O (1).
HashMap

Es importante conocerlas ya que la eleccin del contenedor de los datos


tiene una gran inuencia en el rendimiento de la aplicacin.

J. Gutirrez, Tema 1 (Parte 3)

Algunos tipos del

Curso 12/13

Collections Framework

29/32

Recorrido de colecciones

ndice

Algunos tipos del Collections Framework


Recorrido de colecciones

J. Gutirrez, Tema 1 (Parte 3)

Curso 12/13

30/32

Algunos tipos del

Collections Framework

Recorrido de colecciones

Recorrido de colecciones con un iterador

Tal y como hemos visto, a cualquier objeto que sea una coleccin le
podemos enviar un mensaje para que nos devuelva un iterador.
Collection <T > col = ...;
Iterator <T > it = col . iterator () ;
T dato ;
while ( it . hasNext () ){
dato = it . next () ;
// Procesar el dato
}

Ejemplo:
ArrayList < Figura > figs = new ArrayList < Figura >() ;
// Insertar figuras en el ArrayList
Iterator <T > it = figs . iterator () ;
Figura f;
while ( it . hasNext () ){
f = it . next () ;
// Hacer algo con la figura
}

J. Gutirrez, Tema 1 (Parte 3)

Algunos tipos del

Collections Framework

Curso 12/13

31/32

Recorrido de colecciones

Recorrido de colecciones con un bucle for

Cualquier objeto que sea una coleccin se puede recorrer mediante un bucle
for del siguiente modo:
Collection <T > col = ....;
for (T dato : col ) {
// Hacer algo con el elemento dato
}

Ejemplo:
TreeSet < String > palabras = new TreeSet < String >() ;
// Insertar cadenas en el TreeSet
for ( String p: palabras )
System . out . println ( p);

Este cdigo usa internamente un iterador.

J. Gutirrez, Tema 1 (Parte 3)

Curso 12/13

32/32