Astrazioni Polimorfe e Tipi Generici

Documenti analoghi
Polimorfismo per Genericità in Java

Cosa sono i Generics?

Il linguaggio Java: aggiunte in Java 1.5

Programmazione. ( a.k.a. Generics )

Generics in Java. Linguaggi Corso M-Z - Laurea in Ingegneria Informatica A.A

Programmazione Parametrica ( a.k.a. Generics )

Polimorfismo parametrico vs polimorfismo per inclusione

Generics & Collections

Astrazioni sui dati : Specifica di Tipi di Dato Astratti in Java

Collezioni. (a cura del Prof. Marco Patella)

18 - Vettori. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

Capitolo 6. Uso della gerarchia. c 2005 Pearson Education Italia Capitolo 6-1 / 125

Introduzione Generics Iteratori. Collezioni in Java. Dr. Giulio Pellitta. 13 aprile 2011

Astrazioni sul controllo. Iteratori

Introduzione al Java Collections Framework. Java Collections Framework (cont.) Interfacce del Collections Framework

Introduzione al Java Collections Framework

Java: tipi (im)mutaibili. Metodi equals e clone

STRUTTURE DATI: OLTRE GLI ARRAY LISTE

Subtype Polymorphism. Conversioni di tipo. Conversioni di tipo. Subtyping. Conversioni di tipo. Interfacce e subtype polimorfismo

19 - Eccezioni. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

Corso di Algoritmi e Strutture Dati con Laboratorio. Java Collections Framework (I parte)

Programmazione. Cognome... Nome... Matricola... Prova scritta del 11 luglio 2014

OCA JAVA 8 SE PROGRAMMER I DOCENTE: DOTT. FAUSTO DELL ANNO

La classe Object. L2-Linguaggi di Programmazione II-unina 1

Testo di Riferimento (usato nei corsi precedenti)

16 - Ereditarietà, tipi e gerarchie

Le collezioni di oggetti. Prof. Accarino IIS Altiero Spinelli via Leopardi 132 Sesto San Giovanni

Notazione grafica UML

Programmazione Java Avanzata Programmazione Object- Oriented in Java

3. Il sistema dei tipi I tipi wrapper

Astrazioni sui dati : Ragionare sui Tipi di Dato Astratti

A. Lorenzi, A. Rizzi Java. Programmazione ad oggetti e applicazioni Android Istituto Italiano Edizioni Atlas

Liste doppie. Doubly Linked Lists. GT: 6.2 (e 3.3) Argomenti della lezione

Esempio 2: Subtyping

La classe java.lang.object

Esonero del corso di Programmazione a Oggetti

Programmazione. Cognome... Nome... Matricola... Prova scritta del 22 settembre Negli esercizi proposti si utilizzano le seguenti classi:

Corso di Algoritmi e Strutture dati Programmazione Object- Oriented in Java (Parte I)

Sul pattern Iterator

Esempio su strutture dati dinamiche: ArrayList

Esempio su strutture dati dinamiche: ArrayList

Metodologie di Programmazione. ovvero, Principi e Tecniche per la costruzione di programmi

Programmazione Java Struttura di una classe, Costruttore, Riferimento this

Uguaglianza e copia di oggetti

Fondamenti di Informatica L-B Esercitazione n 6 Java: Collezioni, Classe Wrapper & Generics

Bank. Bank. BankAccount. Bank. Bank. private BankAccount[] conti; // Posizione attuale private int posizioneattuale;...

Metodi di una Collection

Riassunto: cos è la OOP? classi astratte, interfacce, classi interne. Scaletta. Figura con area()? Figura senza area()? Stefano Mizzaro 1.

22 - Strutture Dati (Java Collections Framework)

Esempi in Java di program.ne O-O

14 - Metodi e Costruttori

Il Java Collections Framework

QUEUE : considerazioni. QUEUE : considerazioni. QUEUE : esempio. QUEUE : esempio

Algoritmi e Strutture Dati. Tipo di dato astratto e Strutture dati elementari

Strutture dati. Il che cosa e il come. F. Damiani - Alg. & Lab. 04/05

Corso di Algoritmi e Strutture Dati con Laboratorio. Tipi di dato pila e coda

Ereditarietà (ultima)

Programmazione ad oggetti Prova scritta 15 Gennaio 2013

Argomenti della lezione. Tipo di dato astratto. Array. Tipo di dato Lista. Liste Implementazione di liste in Java Stack Code

Programmazione II Compitino (Vers. B)

Java. Classi Anonime In Java Da Java 1.1 si possono usare classi anonime per implementare interfacce. Espressioni Lambda. Implementazione Interfaccia

Programmazione generica

Corso di Fondamenti di Informatica I

Implementazione Java di un ADT

Le eccezioni in Java

Capitolo 16. Programmazione generica. Cay S. Horstmann Concetti di informatica e fondamenti di Java quarta edizione

Programmazione a oggetti

Programmazione a Oggetti. Eccezioni

Le basi del linguaggio Java

Uso di classi e oggetti. Prof. Francesco Acarino IIS Altiero Spinelli Via Leopardi 132 Sesto San Giovanni

Indice. Prefazione. 3 Oggetti e Java 53

Laboratorio di Programmazione II Corso di Laurea in Bioinformatica Dipartimento di Informatica - Università di Verona

In questa lezione. Polimorfismo

Programmazione a Oggetti Lezione 7. Il linguaggio Java: aspetti generali

Programmazione orientata agli oggetti La classe Object, metodi e classi final, this. Object

Introduzione. Java RTTI RTTI. Il run-time type identification è quella parte di Java che si occupa di controllare i tipi a runtime

Programmazione II Compitino (Vers. B)

Programmazione I. 11 gennaio Considerate la seguente gerarchia di classi (rappresentata mediante un diagramma UML): +f(double x):

La classe Object. Ce li ha anche HelloWorld!!!

TIPI PRIMITIVI E CLASSI WRAPPER

Errata Corrige di Manuale di Java 8

Astrazione Dati. Nicola Fanizzi. Linguaggi di Programmazione [010194] 10 mag, Dipartimento di Informatica Università degli Studi di Bari

Fondamenti di Informatica I

Le liste. ADT e strutture dati per la rappresentazione di sequenze. Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 5

Il linguaggio C. Puntatori e dintorni

OCA JAVA 7 SE PROGRAMMER I DOCENTE: DOTT. FAUSTO DELL ANNO

Fondamenti di Informatica e Laboratorio T-AB T-15 Strutture dati

Esempio su strutture dati dinamiche: ArrayList

Programmazione con Java

L ereditarieta` Riuso del software: Ereditarieta`, Composizione, Polimorfismo e Binding Dinamico Ereditarietà Ereditarietà

Esercitazione n 2. Obiettivi

Oggetti. Interfacce e sottotipi

Implementazione ADT: Alberi

Interfacce. Un interfaccia Java è una collezione di metodi astratti (e di costanti) Un metodo astratto è un metodo non implementato

Input. Il tipo char Alcune modalità di acquisizione di input. Laboratorio di Programmazione - Luca Tesei

Array di array. Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 1. Dispensa 03. A. Miola Febbraio 2008

Il linguaggio Java. La superclasse universale Object

Programmazione ad Oggetti. Java Parte II

cap.6 del testo a cosa servono i tipi nei linguaggi di programmazione cos è un linguaggio type safe

public static boolean occorre (int[] a, int n) { int i = 0; boolean trovato = false;

Transcript:

Astrazioni Polimorfe e Tipi Generici

Polimorfismo Dal Greco molte forme Una variabile polimorfa può riferirsi a oggetti di classi diverse Un metodo polimorfo può avere parametri di tipi diversi Un tipo polimorfo può essere un contenitore di dati di tipi diversi (per esempio stack di oggetti di tipo qualunque ) 2

Polimorfismo Polimorfismo per procedure e iteratori: astrazioni parametriche rispetto al tipo di uno o piu` argomenti Es. e motivazione: invece di costruire una procedura di ordinamento per un vettore di interi, una per per un vettore di stringhe, ecc.,è preferibile unica astrazione procedurale che ordina un vettore, e che sia utilizzabile sia per gli interi che per le stringhe, Polimorfismo per data abstraction: astrazione parametrica rispetto a tipo degli elementi contenuti negli oggetti Es. Invece di un astrazione per insiemi di numeri interi (IntSet) e una per insiemi di stringhe (StrSet), preferibile unica astrazione del concetto di insieme (astrazione Set) utilizzabile sia per gli interi che per le stringhe 3

Esempio: Ricerca sequenziale. public static int cerca(object x, Vector a) { //@requires x!= null && a!=null && (\forall int i; 0<=i<a.size(); //@ a.get(i)!=null); //@ensures \result == -1 && (*non esiste in a elemento equals a x *) //@ x.equals(a.get(\result)) for(int i=0; i<a.size(); i++) if(x.equals(a.get(i)) return i; return 1; Il codice per Object è un astrazione di quello, ad esempio, per int. Similmente, si potrebbe definire cerca(object, Iterator) o cerca(object, Collection) per astrarre ricerca sequenziale a qualunque contenitore 4

Es. Specifica di set polimorfo public class PolimSet { // OVERVIEW: PolimSet sono insiemi mutabili illimitati // oggetto null non può appartenere a un oggetto PolimSet // usato equals per determinare uguaglianza di elementi public PolimSet() // costruttore public void insert (Object x) throws NullPointerException { //@ signals x == null //@ ensures x!=null && (*inserisce x (non un suo clone) in this *) public void remove (Object x) public boolean IsIn (Object x) public boolean subset (PolimSet s) 5

Implementazione (parziale) di PolimSet public class PolimSet{ private ArrayList els; //oppure Vector public PolimSet(){els=new ArrayList(); // oppure Vector() public void insert (Object x) throws NullPointerException { if (getindex(x) < 0) els.add(x); private int getindex(object x){ for(int i=0; i<els.size(); i++) if(x.equals(els.get(i)) return i; return 1; public void remove (Object x){ if (x==null) return; els.remove(x); public boolean IsIn (object x){ public boolean subset (PolimSet s){ 6

Attenzione all implementazione del metodo equals Appartenenza di un elemento a oggetto PolimSet determinata usando equals quindi anche contenuto di un PolimSet dipende da esso Spesso (ad es. per Vector e tutte le classi delle librerie Sun) equals restituisce true se due vettori hanno lo stesso stato: attenzione a immettere oggetti Vector in un PolimSet! PolimSet s = new PolimSet(); Vector x = new Vector(); Vector y = new Vector(); s.insert(x); s.insert(y); x.add(new Integer(3)); if(s.isin(y)) // qsta condizione vale false y non viene aggiunto a causa di equals Questo può essere inatteso (dopo s.insert(y); senza un remove ci si aspetta che y sia ancora in s) soluzione insoddisfacente: usare == invece di equals : non funziona per oggetti immutabili (es: due stringhe identiche nello stesso PolimSet) Soluzione: racchiudere elementi (es. Vector) che si vogliono distinguere in oggetti di una classe contenitore (wrapper) che ridefinisca il metodo equals in maniera opportuna 7

usare un contenitore per gli oggetti mutabili della collezione public class Container{ private Object el; public Container(Object x){el = x; public Object get () {return el; public boolean equals (Object x){ if(! x instanceof Container) return false; return (el == ((Container) x).el); Adesso il codice (con qualche modifica) funziona come ci aspettiamo PolimSet s = new PolimSet(); Vector x = new Vector(); Vector y = new Vector(); s.insert(new Container(x)); s.insert(new Container(y)); x.add(new Integer(3)); if(s.isin(new Container (y))) // condizione vera 8

Accorgimenti nell uso di collezioni polimorfe Le collezioni polimorfe (e.g., PolimSet) sono definite rispetto a elementi di classe Object, quindi bisogna incapsulare (wrap) i tipi primitivi: int Integer i metodi osservatori che restituiscono elementi della collezione restituiranno oggetti di tipo Object, quindi occorre fare il casting e nel caso di tipi primitivi estrarre (unwrap) a volte wrap e unwrap evitati grazie ad autoboxing e autounboxing PolimSet s = new PolimSet(); s.insert(new Integer(3)); Iterator g = s.elements(); while (g.hasnext()){ incapsulamento ed estrazione del tipo primitivo casting int i = (Integer)g.next(); //NB: autounboxing 9

Problema con astrazioni polimorfe Il vincolo che gli elementi di una collezione siano tutti dello stesso tipo non può essere controllato dal compilatore! quindi possono verificarsi errori di classe a run-time (che non si verificano, e.g., con IntSet). Esempio List myintlist = new LinkedList(); // 1 myintlist.add(new Integer(0)); // 2 Integer x = (Integer) myintlist.iterator().next(); // 3 Il cast in linea 3 è noioso : il programmatore sa cosa c è nella lista. Se pero la riga (2) fosse: myintlist.add(new String(0)); // 2 allora l oggetto restituito in linea 3 non sarebbe un Integer, causando un errore run time! Come fare a evitarlo? Noi vorremmo type safety! Questo è un problema ineliminabile fino al JDK 1.4 incluso, in quanto è necessario usare il casting Risolto in Java 1.5 con i tipi generici 10

Classi Generiche Generici forniscono un astrazione sui tipi, simile alle astrazioni polimorfe ma più sicure (type-safety è sempre garantita) Esempio di lista di interi con i generici List<Integer> myintlist = new LinkedList<Integer>(); // 1 myintlist.add(new Integer(0)); //2 Integer x = myintlist.iterator().next(); // 3 alla riga 3 non serve più il cast: il compilatore sa che la lista contiene solo oggetti Integer se la riga 2 fosse: myintlist.add(new String(0)); // 2 non ci sarebbe bisogno di mandare in esecuzione il programma per accorgersi dell errore: ce lo segnalerebbe il compilatore 11

Classi Generiche Esempi di classi generiche: le interfacce List e Iterator public interface List<E> { void add(e x); Iterator<E> iterator(); public interface Iterator<E> { E next(); boolean hasnext(); public interface IntegerList { void add(integer x) Iterator<Integer> iterator(); - parti tra parentesi angolate sono parametri formali della classe generica; tipico indentificatore, singola lettera maiuscola - List<Integer> e Iterator<Integer> sono invocazioni della classe generica, con parametro attuale Integer - NB: non si crea una classe nuova (nessuna duplicazione di codice, al contrario dei template di C++) così come non si crea nuovo codice quando si invoca un metodo passandogli i parametri attuali 12

Genericità e Sottotipi Attenzione: alcune cose sembrano andare contro l intuizione List<String> ls = new ArrayList<String>(); List<Object> lo = ls; lo.add(new Object()); // ERRORE IN COMPILAZIONE String s = ls.get(0); // ERRORE: tenta di assegnare un Object a unastring! Domanda fondamentale: una lista di String è una lista di Object? NO! altrimenti tramite una variabile lista di Object si può inserire un Object in una lista di String e quando si tenta di estrarre, tramite una variabile lista di String, un oggetto String, si verifica un errore In generale, se Gen<T> è una classe generica e se ClassB è sottoclasse di ClassA allora Gen<ClassB> NON è sottoclasse di Gen<ClassA> (NB: a maggior ragione una lista di Object NON è sottoclasse di una lista di String) 13

Genericità e Sottotipi: i tipi jolly (1) Rimane problema di definire sottoclassi di classi ottenute per invocazione di classi generiche, per realizzare polimorfismo, e.g., nei metodi che hanno parametri contenitori Esempio: un metodo che stampi tutti gli elementi di una collezione void printcollection(collection<object> c) { for (Object e : c) { System.out.println(e); Non va: parametro attuale deve essere stesso tipo o sottotipo, ma Collection<Object> non ha alcun sottotipo nessun polimorfismo Occorre definire il tipo supertipo di tutte le collezioni ottenute per invocazione di Collection<E> questo è Collection<?> (leggi: Collection di sconosciuto ) void printcollection(collection<?> c) { for (Object e : c) { System.out.println(e); 14

Genericità e Sottotipi: i tipi jolly (2) L inserzione di elementi NON è possibile! Collection<?> c; c = new ArrayList<String>(); c.add(new Object()); // errore di compilazione NB: il tipo statico di c dice che il tipo dell elemento della collezione è sconosciuto (può essere qualsiasi) tipo del parametro attuale di add deve essere sottotipo di qualsiasi altro tipo non esiste tale tipo; unico valore attuale ammissibile è null NB: è comunque possibile fare una c.get() e assegnare il risultato a una variabile di tipo Object, perchè qualsiasi cosa estratto dalla get è un Object. 15

Tipi jolly limitati Ad esempio Per definire un metodo drawall che accetti liste di qualsiasi sottotipo di Shape public void drawall(list<? extends Shape> shapes) {... <? extends Shape> è un esempio di jolly limitato Rappresenta un tipo sconosciuto, di cui si sa che estende Shape Shape è il suo limite superiore (upper bound) classe Shape Solito problema con gli inserimenti public void addrectangle(list<? extends Shape> shapes) { shapes.add(0, new Rectangle()); // Errore: shapes di fatto // è in sola lettura perchè il tipo del componente del parametro shapes è un sottotipo sconosciuto di Shape: non è garantito che sia un supertipo di Rectangle 16

Metodi Generici (1) Es: Metodo che travasa tutti gli oggetti di un array in una collezione static void fromarraytocollection(object[] a, Collection<Object> c) { for (Object o : a) { c.add(o); Non funziona: Perchè? static void fromarraytocollection(object[] a, Collection<?> c) { for (Object o : a) { c.add(o); Non funziona neanche questo: Perchè? Il modo giusto è usare metodi generici, che hanno uno o più parametri che rappresentano tipi. static <T> void fromarraytocollection(t[] a, Collection<T> c) { for (T o : a) { c.add(o); per rendere corretta l inserzione c.add(o) dobbiamo chiamare fromarraytocollection con parametri in cui il tipo dell elemento della collezione sia supertipo di quello dell array NB: non occorre indicare esplicitamente parametri attuali in corrispondenza ai parametri formali di un metodo generico: ci pensa il compilatore a inferire il tipo del parametro attuale scegliendo il tipo più specifico (il minimo, nell ordinamento tra tipi definito dalla gerarchia di ereditarietà, tra tutti quelli che rendono legale l invocazione del metodo generico) 17

Metodi Generici (2) Esempi di inferenza dei tipi da parte del compilatore String[] sa = new String[100]; Collection<String> cs = new ArrayList<String>(); fromarraytocollection(sa, cs);// T inferred to be String Collection<Object> co = new ArrayList<Object>(); fromarraytocollection(sa, co);// T inferred to be Object Integer[] ia = new Integer[100]; fromarraytocollection(ia, cs);// compile-time error: String NON è supertipo di Integer 18

Possono apparire intercambiabili: Metodi generici vs jolly (1) interface Collection<E> { public boolean containsall(collection<?> c); public boolean addall(collection<? extends E> c); interface Collection<E> { public <T> boolean containsall(collection<t> c); public <T extends E> boolean addall(collection<t> c); Quale dei due stili è preferibile? Notiamo che Nei due metodi il parametro T compare una sola volta, non vincola il valore restituito dal metodo e gli altri parametri del metodo T serve solo per il polimorfismo, ma per questo basterebbero i tipi Jolly I metodi generici servono per esprimere dipendenze tra gli argomenti del metodo oppure tra gli argomenti e il tipo restituito 19

Metodi generici vs jolly (2) Possibile anche l uso combinato dei due class Collections { public static <T> void copy(list<t> destinazione, List<? extends T> sorgente){... alternativamente, senza tipi jolly class Collections { public static <T, S extends T> void copy(list<t> dest, List<S> src){... 20