Cosa sono i Generics?

Documenti analoghi
Cosa sono i Generics?

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

Generic. Contenitori generici per oggetti realizzati tramite il concetto di tipo parametrico. IL NUOVO APPROCCIO (java 1.5)

Java (J2SE) 1.5 (5.0)

Polimorfismo per Genericità in Java

Programmazione. ( a.k.a. Generics )

Programmazione Parametrica ( a.k.a. Generics )

Il linguaggio Java: aggiunte in Java 1.5

Polimorfismo. Astrazioni Polimorfe e Tipi Generici. Esempio: Ricerca sequenziale. Polimorfismo

Astrazioni Polimorfe e Tipi Generici

Programmazione Parametrica ( a.k.a. Generics )

Programmazione ad oggetti

Collezioni, mappe e iteratori (a cura del Prof. Marco Patella)

STRUTTURE DATI IN JAVA

Cenni su programmazione con tipi generici (generics)

Conoscere l uso delle collezioni in Java. Conoscere il concetto di Generics (programmazione

Collezioni. (a cura del Prof. Marco Patella)

Programmazione Parametrica ( a.k.a. Generics )

Java generics PR

Generics & Collections

Corso di Fondamenti di Informatica I

Java Generics. Sunto di quanto letto nel libro Java Generics and Collections di Maurice Naftalin & Philip Wadler O'REILLY

Programmazione orientata agli oggetti Classi astratte e interfacce

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

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

Programmazione orientata agli oggetti Classi astratte e interfacce. Classi astratte - Interfacce

Programmazione orientata agli oggetti Classi astratte e interfacce. Classi astratte - Interfacce

18 - Classi parzialmente definite: Classi Astratte e Interfacce

17 - Classi parzialmente definite: Classi Astratte e Interfacce

Esempio 2: Subtyping

Corso di Linguaggi di Programmazione

9 - Array. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

Testo di Riferimento (usato nei corsi precedenti)

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

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

Gerarchie e polimorfismo: liste

Programmazione a Oggetti. Polimorfismo e Tipi Generici

PROGRAMMAZIONE 2 4. Java: un modello operazionale

JAVA GENERICS. Angelo Di Iorio Università di Bologna

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

OLTRE LE CLASSI OLTRE LE CLASSI

La classe java.lang.object

Corso di Linguaggi di Programmazione

Corso di Progettazione del Software

Le classi in java. Un semplice programma java, formato da una sola classe, assume la seguente struttura:

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

INFORMATICA III Parte B -Progettazione e Algoritmi

E21 Esercizi sulle collezioni in Java

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

Polimorfismo parametrico vs polimorfismo per inclusione

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

Fondamenti di informatica Oggetti e Java. Luca Cabibbo. Collezioni++ (Aggiunte di Marco Patella) Capitolo 26.bis. aprile 2006.

Laboratorio di Sistemi Polimorfismo Java. Prerequisiti: per la comprensione dell'articolo è necessario conoscere il concetto di Ereditarietà in Java.

Java generics PR

Linguaggi di programmazione II AA 2010/2011 Esercitazione 2

PROGRAMMAZIONE Gerarchie di tipi: implementazioni multiple e principio di sostituzione

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

Programmazione. Cognome... Nome... Matricola... Compitino del 17 gennaio 2007

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

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

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

Agent and Object Technology Lab Dipartimento di Ingegneria dell Informazione Università degli Studi di Parma. Ingegneria del software A

Programmazione. Cognome... Nome... Matricola... Prova scritta del 20 febbraio 2012

LINKEDLIST: implementazione iteratore. LINKEDLIST: iteratore INNERITERATOR INNERITERATOR

Esercizio: Lista Circolare

Parte I Java. Metodologie di Programmaziona Secondo Appello, 14/2/2006 1

Concetti Base Encapsulation ed Ereditarietà Programmare con l Ereditarietà. Java: Ereditarietà. Damiano Macedonio

Esempi al calcolatore su: 1) Costruttori ed ereditarietà 2) Subtyping e Polimorfismo

Esempi al calcolatore su: 1) Costruttori ed ereditarietà 2) Subtyping e Polimorfismo

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

Collezioni in Java. Emilio Di Giacomo e Walter Didimo

ALGORITMI E STRUTTURE DATI

Scope e visibilità per classi

Introduzione al Java Collections Framework

ArrayList. Prof. Francesco Accarino IIS Altiero Spinelli Via Leopardi132 Sesto San Giovanni

Corso di Linguaggi di Programmazione

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

Implementare un'interfaccia

Programmazione in Java (I modulo) Lezione 20: Ereditarietà

TIPI PRIMITIVI: LIMITI

Java Le stringhe. Stringhe

Programmazione ad oggetti

# $ $ A.A. 2006/07 Tutor: Daniele Tiles &== ? &7$ %% & '( ) * + $, $ $ -' %./, $ * $ $ 7 5 &7 2$ $ $ 3&4&&&

Riuso di classi. Ereditarietà. Ereditarietà. Spesso si ha bisogno di classi simili

Oggetti e classi. Cos è un oggetto

Arrays Array L ay ist

Programmazione Java Avanzata Programmazione Object- Oriented in Java

tipi di dato astratti

Interfacce. Esempio: interfaccia I con una sola funzione g() public interface I {

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

Le gerarchie di tipi: implementazioni multiple e principio di sostituzione

Array. Walter Didimo

TIPI PRIMITIVI E CLASSI WRAPPER

Esempio su strutture dati dinamiche: ArrayList

14 - Metodi e Costruttori

Richiami Java e Arrays

Transcript:

Linguaggi Corso M-Z - Laurea in Ingegneria Informatica A.A. 2008-2009 Alessandro Longheu http://www.diit.unict.it/users/alongheu alessandro.longheu@diit.unict.it - lezione 22 - Generics in Java 1 Cosa sono i Generics? Un generic è uno strumento che permette la definizione di un tipo parametrizzato, che viene successivamente esplicitato in fase di compilazione secondo le necessità (simile ai template C++). Svantaggi: Invece di: List words = new ArrayList(); Si definisce: List<String> words = new ArrayList<String>(); Vantaggi: Fornisce una migliore gestione del type checking durante la compilazione Evita il casting da Object. I.e., invece di: String title = ((String) words.get(i)).touppercase(); utilizzeremo String title = words.get(i).touppercase(); 2

Cosa sono i Generics? Per permettere una maggiore genericità si potrebbe rilassare il controllo sui tipi, ma questo presta il fianco ad errori È sbagliato abolire il controllo di tipo! Occorre un altro modo per esprimere genericità, che consenta un controllo di tipo a compile time, in modo da garantire la type safety: "se si compila, è certamente corretto" Java 1.5 introduce i tipi parametrici ("generici") Il tipo può essere un parametro: in attributi e metodi di classi, purche non statici; la notazione è NomeClasse<TIPO> se serve indicare un oggetto di classe NomeClasse, o semplicemente TIPO nei punti dove c era Object Si possono definire relazioni fra tipi generici, quindi si recupera il "lato buono" dell'ereditarietà, inquadrandolo in un contesto solido. 3 Una classe parametrica class tipo <T> { T attributo; public tipo (T x){attributo = x; public T getvalue() {return attributo; 4

Uso della classe parametrica public class Prova { public static void main(string []s){ tipo <String> p1 = new tipo<string>(s[0]); tipo <Integer> p2 = new tipo<integer>(10); String a = p1.getvalue(); System.out.println(a); Integer b = p2.getvalue(); System.out.println(b); 5 Generics dalla 1.5 Tutta la JFC è stata riscritta dalla versione 1.5 per far uso dei generici Anche classi preesistenti (come Vector) sono state reingegnerizzate e riscritte in accordo al nuovo idioma Le operazioni sulla JFC "generica" si dicono checked (controllate) o type-safe (sicure come tipo) 6

Uso dei Generics public interface List<E> { void add(e x); Iterator<E> iterator(); public interface Iterator<E> { E next(); boolean hasnext(); List<Integer> myintlist = new LinkedList<Integer>(); // 1 myintlist.add(new Integer(0)); //2 Integer x = myintlist.iterator().next(); // 3 List myintlist = new LinkedList(); // 1 myintlist.add(new Integer(0)); // 2 Integer x = (Integer)myIntList.iterator().next(); // 3 Tipi parametrizzati, perchè tutte le occorenze del parametro formal type (E in questo caso) sono sostituite dagli argomenti actual type 7 (in questo caso Integer). Comportamento dei Generics Il bytecode dello stesso codice con e senza generici è identico: List List<String> <List<List<String>> sono identici in bytecode e corrispondono alla plain old List. L Erasure è il processo che converte il programma scritto con i generici nella forma senza generici che rispecchia più da vicino il bytecode prodotto. Il termine Erasure non è proprio corretto in quanto vengono rimossi i generici, ma aggiunti i cast. L aggiunta dei cast è implicita, e java fornisce la Cast-iron guarantee: il cast implicito aggiunto dalla compilazione dei generici NON DEVE MAI FALLIRE. Questa regola si applica solo per il codice che non presenta unchecked warnings. I vantaggi dell'implementazione via Erasure sono: mantiene le cose semplici (non c'è nulla di nuovo) mantiene le cose piccole (una sola implementazione di List) semplifica l'evoluzione (la stessa libreria può essere acceduta da 8 codice generico e da codice legacy)

Ereditarietà dei tipi generici In generale, se C2 è una classe derivata da C1 e G è una dichiarazione generica, non è vero che G<C2> è un tipo derivato da G<C1>. List<String> ls = new ArrayList<String>(); //1 List<Object> lo = ls; //2 L istruzione 2 genera un errore in compilazione 9 Ereditarietà dei tipi generici Se B deriva da A, NON si può dire che una collezione di elementi di B derivi dalla collezione di elementi di A, perché in generale ciò non ha senso (operazioni impossibili) ALCUNE operazioni potrebbero anche essere sicure (negli array, la lettura), ma ciò non è vero in generale. 10

Ereditarietà dei tipi generici Consideriamo la classe generica LinkedList <T>: prendiamo due sue "istanziazioni" LinkedList <Number> LinkedList<Integer> Sono due tipi diversi, incompatibili fra loro, anche se Integer estende Number; situazione in contrasto a quella che si verifica negli array, dove Integer[] è un sottotipo di Number[]. Per verificarlo, creiamo due liste: LinkedList<Number> l1 = new LinkedList<Number>(); LinkedList<Integer> l2 = new LinkedList<Integer>(); e consideriamo i due possibili assegnamenti l1 = l2 e l2 = l1; si ottiene in ogni caso errore perché LinkedList<Integer> non estende LinkedList<Number> 11 Ereditarietà dei tipi generici Gli assegnamenti in precedenza sono impossibili perché viene violato il (noto) principio di sostituzione: Ad una variabile di un dato tipo può essere assegnato un valore di ogni sottotipo e un metodo con un argomento di un dato tipo può essere chiamato con un argomento di ogni sottotipo. List<Number> numbers = new ArrayList<Number>(); numbers.add(2); numbers.add(3.14d); assert numbers.tostring().equals("[2, 3.14]"); Qui il principio vale fra List e ArrayList e fra Number e Integer e Double rispettivamente. List<Integer> invece NON E' UN SOTTOTIPO di List<Number> in quanto viene violato il principio di sostituzione, ad esempio: List<Integer> integers = Arrays.asList(1, 2); List<Number> numbers = integers; // non compila! numbers.add(3.14d); assert integers.tostring().equals("[1, 2,3.14]"); 12

Tipi parametrici varianti L'esperimento precedente ha mostrato che non ha senso cercare una compatibilità generale fra tipi parametrici, perché non può esistere. Ha senso invece cercare compatibilità fra casi specifici e precisamente fra tipi di parametri di singoli metodi. Perciò, alla normale notazione dei tipi generici List<T>, usata per creare oggetti, si affianca una nuova notazione, pensata esplicitamente per esprimere i tipi accettabili come parametri in singoli metodi Si parla quindi di tipi parametrici varianti, in Java più brevemente detti WILDCARD. 13 Tipi parametrici varianti la notazione List<T> denota il normale tipo generico il tipo covariante List<? extends T> fattorizza le proprietà dei List<X> in cui X estende T il tipo controvariante List<? super T> fattorizza le proprietà dei List<X> in cui X è esteso da T il tipo bivariante List<?> fattorizza tutti i List<T> senza distinzione (equivale a scrivere List<? extends Object>) Vale il cosiddetto Get and Put PRINCIPLE: si usa extends quando si devono solo estrarre valori da una struttura Relativamente al tipo controvariante, poiché la classe supertipo potrebbe essere qualsiasi, fino ad Object, i metodi a cui si potrebbe ricorrere entro il codice che contiene il tipo controvariante non possono essere i metodi di T, ma al massimo quelli di Object, sicuramente supportati, quindi questa wildcard non permette di operare efficacemente e si usa quando si devono solo inserire valori in una struttura (senza farci null altro); diviene necessario nei casi in cui si debbano copiare elementi da una collezione ad un altra di un suo supertipo, che si ipotizza accessibile come parametro del metodo. non si usano wildcard quando si devono sia estrarre che inserire valori nella stessa struttura. 14

Tipi parametrici varianti void printcollection(collection c) { Iterator i = c.iterator(); while (i.hasnext()){ //for (k = 0; k < c.size(); k++) { System.out.println(i.next()); void printcollection(collection<object> c) { for (Object e : c) { System.out.println(e); Wildcards void printcollection(collection<?> c) { for (Object e : c) { System.out.println(e); 15 Tipi parametrici varianti public class MyList<T> { private T head; private MyList<T> tail; public T gethead(){ return head; public <E extends T> void sethead(e element){ head=element; MyList<Number> list1 = new MyList<Number>(); MyList<Integer> list2 = new MyList<Integer>(); list1.sethead( new Double(1.4) ); // OK! list1.sethead( list2.gethead() ); // OK! 16

Tipi parametrici varianti public class MyList<T> { private T head; private MyList<T> tail; public T gethead(){ return head; public <E extends T> void sethead(e element){ head=element; public void settail(mylist<t> l){ tail=l; public MyList<? extends T> gettail(){ return tail; Restituisce una lista di elementi di tipo T o più specifico di T MyList<? extends Number> list3 = list1.gettail(); MyList<? extends Number> list4 = list2.gettail(); MyList<? extends Integer> list5 = list2.gettail(); I primi due restituiscono una lista di Number, compatibile col tipo "lista di qualcosa che estenda Number Il terzo restituisce una lista di Integer, compatibile col tipo "lista di qualcosa che estenda Integer" 17 Tipi parametrici varianti public class MyList<T> { private T head; private MyList<? extends T> tail; public T gethead(){ return head; public <E extends T> void sethead(e element){... public MyList<? extends T> gettail(){ return tail; public void settail(mylist<? extends T> l){ tail=l; Non c'è realmente bisogno che la coda sia una lista di T! Possiamo essere più generici! Conseguentemente, possiamo rilassare il vincolo su settail, il cui argomento ora può essere una lista di qualunque cosa estenda T list1.settail(list2); // SI', ORA VA BENE! Si rendono così SELETTIVAMENTE possibili TUTTE e SOLE le operazioni "sensate" e significative! 18

Tipi parametrici varianti Nell'esempio precedente abbiamo usato: il tipo generico MyList<T> per creare oggetti MyList<Number>, MyList<Integer>, tipi covarianti come MyList<? extends Number> fattorizza le proprietà dei tipi di liste che estendono Number, come MyList<Integer>, MyList<Double>, o MyList<Number> stessa NON abbiamo invece usato: tipi controvarianti come MyList<? super Number> fattorizzerebbe le proprietà di tutte le liste di tipi più generici di Number, come ad esempio MyList<Object> il tipo bivariante MyList<?> 19 Tipi parametrici varianti public abstract class Shape { public abstract void draw(canvas c); public class Circle extends Shape { private int x, y, radius; public void draw(canvas c) {... public class Rectangle extends Shape { private int x, y, width, height; public void draw(canvas c) {... public void drawall(list<shape> shapes) { for (Shape s: shapes) { s.draw(this); public void drawall(list<? extends Shape> shapes) {... 20

Tipi parametrici varianti List<? extends Shape> è un esempio di bounded wildcard. Il simbolo? Sta per un tipo sconosciuto Sappiamo che in questo caso tale tipo sconosciuto è un subtype di Shape. Diremo che Shape è un upper bound di una wildcard. 21 Tipi parametrici varianti Supponiamo di voler scrivere un metodo che prende un array di objects e pone gli oggetti dell array in una collection. Soluzione: static void fromarraytocollection (Object[] a, Collection<?> c) { for (Object o : a) { c.add(o); // compile time error 22

Tipi parametrici varianti I metodi generici consentono di superare un tale problema. Cosi come in una dichiarazione di tipo, la dichiarazione di un metodo può essere generica cioè parametrizzata rispetto ad uno o più parametri static <T> void fromarraytocollection (T[] a, Collection<T> c) { for (T o : a) { c.add(o); // correct 23 Argomenti avanzati su Generics Siti in cui è possibile trovare argomenti avanzati sui generics: http://home.dei.polimi.it/ghezzi/_private/generics_paper.pdf http://www.jugpadova.it/files/jugpd41_zoleo_generics.pdf 24