corso di programmazione ed algoritmi master di bioinformaticabaldoni/didattica/aa0203/master... ·...
TRANSCRIPT
Oggetti, classi,ereditarieta`
Corso di Programmazione ed Algoritmi
Master di BioInformatica
Matteo BaldoniDipartimento di InformaticaUniversita` degli Studi di TorinoC.so Svizzera, 185 I-10149 Torino
[email protected]://www.di.unito.it/~baldoni/didattica
2
Chi sono? Come contattarmi?Matteo Baldoni
Dipartimento di InformaticaUniversità degli Studi di TorinoCorso Svizzera, 185I-10149 Torino (ITALY)
e-mail: [email protected]: http://www.di.unito.it/~baldoniTel.: +39 011 670 67 56Fax.: +39 011 75 16 03
Pagina del corso:http://www.di.unito.it/~baldoni/didattica/
“Sono nato a Torino nel 1968, nel febbraio1993 mi sono laureato con lode in Scienzedell’Informazione e nel febbraio 1998 sonodiventato Dottore in Ricerca in Informatica.Dal luglio 1999 sono ricercatore inInformatica presso il Dipartimento diInformatica dell’Università degli Studi diTorino.”
3
Ogni oggetto haun’interfacciae ogni oggetto ha untipo
4
Oggetti
Un oggetto rappresenta un dato, ed è costituito da
� stato: collezione di variabili� comportamento: collezione di operazioni (metodi)
Esempio - contatoreSTATO
int c;METODI
void iniz(int i) inizializza il contatore a ivoid incr() incrementa il contatore di 1void decr() decrementa il contatore di 1int val() restituisce il valore del
contatore
5
Incapsulamento� I dati e le procedure che li manipolano sono raggruppati in
un’unica entità, l’oggetto.� Il mondo esterno ha accesso ai dati solo tramite un
insieme di operazioni (metodi) che costituisconol’interfaccia dell’oggetto. I dettagli dell’implemen-tazionesono nascosti (INFORMATION HIDING)
� Un oggetto realizza una ASTRAZIONE DEI DATI
6
Contatore
void iniz(int i)void incr()void decr()int val()
INTERFACCIA IMPLEMENTAZIONE
CONTATORE
int c;void iniz(int i) {c=1;}void incr() {++c;}void decr() {--c;}int val() {return c;}
7
Invio di Messaggi� Un programma è costituito da un insieme di oggetti.� Gli oggetti sono dinamici - creati e distrutti durante
l'esecuzione del programma.� Un oggetto A, per agire su un altro oggetto B, invia un
messaggio a B chiedendogli di eseguire uno dei metodidella sua interfaccia.
� Lo scambio di messaggi è l'unico modo di comunicare traoggetti
Es.: esegui ilmetodo m1
8
Invio di Messaggi
finestra
0
esegui incr()
c
bottone 1
contatore
invia valore di c
display
bottone 2
bottone 3
9
Invio di Messaggi
� invio di messaggio = invocazione di un metodo� In Java, e altri linguaggi, si usa la notazione con il punto:oggetto.metodo(…)
3
10
cont1
cont2
int x,y;cont1.incr();cont2.decr();x = cont1.val();y = cont2.val();
x ha valore 4 e y ha valore 9
10
Invio di Messaggi
� In un linguaggio tradizionale, per eseguire una operazionesu un dato, dovremmo passare il dato come parametro:� incr(cont1) o iniz(cont1, 3)
� Nella programmazione ad oggetti, invece, l'oggetto su cui siesegue una operazione non viene passato comeparametro, perché figura già come destinatario delmessaggio (può essere considerato come un parametroimplicito)� cont1.incr() o cont1.iniz(3)
11
Classi
� I più diffusi linguaggi ad oggetti sono basati sul concetto diclasse come insieme di oggetti con struttura ecomportamento simili
� La classe definisce un tipo� Istanza di una classe = oggetto della classe
Istanze
3 10
cont1 cont2
12
Classi (Java)
� Una classe realizza l'implementazione di un tipo di datoastratto.
� In Java:
class Contatore {int c;void iniz(int i) {c = i;}void incr() {++c;}void decr() {--c;}int val() {return c;}
}
13
Classi (Java)
� Per realizzare information hiding si usano le paroleriservate� public - interfaccia� private - implementazione
� Per il momento trascuriamo questo aspetto
class Contatore {private int c;public void iniz(int i) {c = i;}public void incr() {++c;}public void decr() {--c;}public int val() {return c;}
}
14
Variabili private (Java)
� Si noti che, se la variabile c fosse public, il metodo valsarebbe inutile: per conoscere il valore di un contatorecont basterebbe usare cont.c
� Tuttavia è buna norma di programmazione impedirel’accesso diretto alle variabili di un oggetto, dichiarandoleprivate.
class Contatore {private int c;public void iniz(int i) {c = i;}public void incr() {++c;}public void decr() {--c;}public int val() {return c;}
}
15
Tipi
� Java è un linguaggio tipato: tutte le variabili hanno un tipo.� Il tipo di una variabile deve sempre essere dichiarato e può
essere:� una classe� un tipo primitivo
Contatore cont;int x,y;char ch;
16
Tipi di dato primitivi (Java)
� Java fornisce diversi tipi semplici primitivi.� A differenza di altri linguaggi, la dimensione dei tipi
numerici è fissata per consentire la portabilità deiprogrammi:
� byte 8 bit� short 16 bit� int 32 bit� long 64 bit� float 32 bit� double 64 bit� char 16 bit (Unicode)� boolean
17
Come si crea un’istanza
� new Contatore()
� Crea un nuovo oggetto di tipo Contatore e ne restituisce ilpuntatore (handle)
� Tutti gli oggetti sono allocati dinamicamente (quando siesegue la new) e sono manipolati attraverso una handle(puntatore) (assegnamento, passaggio di parametri)
18
Gestione della memoria
� Nella maggior parte dei linguaggi di programmazione leattivazioni di procedure sono gestite con uno stack (pila)
� Quando una procedura è chiamata, si inserisce un recorddi attivazione in cima alla pila, e lo si toglie quandol'esecuzione della procedura termina
� Un record di attivazione contiene le informazioni sulcontrollo (indirizzo di ritorno) ed i dati locali
� Possibilità di chiamate ricorsive di procedure
19
Gestione della memoria
Codice
STATICAdati globali
STACKrecord di attivaz.
dati locali
HEAPdati dinamici
20
Recupero della memoria
� Garbage collection (Scheme, Prolog, Java)
� Il programmatore può solo allocare dati dinamici
� Una procedura di sistema, il garbage collector, sipreoccupa di recuperare tutte le aree di memoria nelloheap non più raggiungibili in modo da poterle riutilizzare
� Altri linguaggi come Pascal o C lasciano al programmatorela responsabilità di recuperare la memoria, con possibilitàdi commettere errori
21
Allocazione dinamicaContatore cont1, cont2; cont1
cont2
22
Allocazione dinamicaContatore cont1, cont2;cont1 = new Contatore();cont2 = new Contatore();cont1.iniz(3);cont2.iniz(10);
cont1
cont23
10
HEAP
23
Allocazione dinamicaContatore cont1, cont2;cont1 = new Contatore();cont2 = new Contatore();cont1.iniz(3);cont2.iniz(10);cont2 = cont1;
cont1
cont23
10
HEAP
Questo oggetto non è più accessibile.Può essere recuperato dal garbagecollector.
24
Puntatori (Java)
� In Java non esistono puntatori espliciti
Contatore cont;
� Fino a quando non si esegue una new, la variabile cont nonè associata a nessun oggetto
� Viceversa in C++ si può dichiarare
sia Contatore cont1; sia Contatore *cont2;
� cont1 è associato ad un contatore creato "staticamente”,cont2 è associato ad un contatore creato dinamicamente(vedi Java)
25
Come si inizializza un oggetto
� Si può chiamare esplicitamente un metodo diinizializzazione:
Contatore cont1;
cont1 = new Contatore();
cont1.iniz(3);
� L'inizializzazione di un oggetto è una operazione moltoimportante.
� Java (e C++) forniscono la nozione di costruttore, checonsente di inizializzare automaticamente un oggetto almomento della creazione.
26
Costruttori
� L'oggetto viene inizializzato al momento della creazione,invocando automaticamente il costruttore.
� L’istruzione Contatore cont1 = new Contatore(3); creaun contatore e lo inizializza a 3.
class Contatore {int c;Contatore(int i) {c = i;}void incr() {++c;}void decr() {--c;}int val() {return c;}
}
costruttore
27
Overloading di metodi(e costruttori)� Overloading: metodi diversi possono avere lo stesso nome.� I metodi "overloaded" si distinguono uno dall'altro in base
alla lista dei tipi degli argomenti.
class Contatore {int c;Contatore() {c = 0;}Contatore(int i) {c = i;}void incr() {++c;}void incr(int n) {c += n;}void decr() {--c;}int val() {return c;}
}
28
Il costruttore di “default” in Java� Se una classe non ha alcun
costruttore è presente un costruttoredi “default” NomeDellaClasse() (chenon esegue nessuna operazioneparticolare)
� Se una classe ha invece unqualsiasi costruttore il costruttore di“default” non viene piu` aggiunto equindi se lo si desidera deve essereesplicitamente aggiunto.
class Contatore { int c; ContatoreContatore() () {}{} void incr() {++c;} void incr(int n) {c += n;} void decr() {--c;} int val() {return c;}}
class Contatore { int c; Contatore() {} Contatore(int i) {c = i;} void incr() {++c;} void incr(int n) {c += n;} void decr() {--c;} int val() {return c;}}
29
I tipi semplici non sono oggetti (Java)
� I tipi semplici, come ad es. gliinteri, non vengono allocatidinamicamente nello heap, adifferenza di altri linguaggi "puri"come Smalltalk
� Esistono classi wrapper chetrasformano tipi semplici inoggetti
Contatore cont;cont = new Contatore(3);int x = 10;
cont
x
3
HEAP
30
THIS
� Come può un oggetto mandare un messaggio a se stesso,ossia invocare un proprio metodo?
� Con la parola chiave this
class A { ... void p() {...} void m() { ... this.p(); ...}}
si può anche scrivere solo p()this viene aggiunto dal compilatore
In alcuni casi thisè indispensabile
31
THIS come costruttore
� this da solo indica un costruttore della stessa classe
class Contatore {int c;Contatore(int n) {c=n;}Contatore() {this(10);}void incr() {++c;}void decr() {--c;}int val() {return c;}
}
chiama il costruttorecon un argomento(inizializza il contatorea 10)
32
Variabili e metodi di classe
� E' possibile definire variabili (o metodi) associate ad unaclasse, condivise da tutte le istanze di quella classe
� In Java sono individuate dalla parola chiave static
class Conta {static int numContatori = 0;int c;Conta(int i) {c = i;
++numContatori;}void incr() {++c;}void decr() {--c;}int val() {return c;}
}
33
Variabili e metodi di classe
� Le variabili di classe sono visibili da tutte le istanze dellaclasse.
� Sono variabili globali (per tutte le istanze di una classe).
2
classeConta
numContatori
8
5c
c
cont1
cont2
34
Variabili e metodi di classe
� Una classe può essere considerata come un oggetto (ditipo Class) che viene allocato staticamente (all'iniziodell'esecuzione del programma)
� Le variabili ed i metodi di classe (static) sono accessibiliattraverso il nome della classe
int x,y;Conta cont = new Conta(3);cont.incr();....x = cont.c;y = Conta.numContatori;
35
Programmi in Java
� Un programma in Java è una collezione di classi� Una di queste deve contenere un metodo main� L'esecuzione inizia dal main
� Il metodo main deve essere statico, perché altrimentibisognerebbe creare un oggetto della classe Esempioprima di poterlo eseguire
class Esempio {public static void main(String arg[]) {
System.out.println("questo è un esempio");}
}
36
Compilazione di un programma in Java
� Si crea un file <nome_file>.java contenente una o più classiC1, C2, … e lo si compila.
> javac <nome_file>.java
� Il compilatore crea un file .class in codice intermedio(bytecode) per ogni classe contenuta nel file .java:
C1.class, C2.class, ...
37
Esecuzione di unprogramma in Java
� Si chiama l'interprete su una classe che contiene il main(Es. C1)
> java C1
� L'interprete alloca questa classe e comincia ad eseguire ilmain.
38
Un programma completo
class Contatore {int c;Contatore(int n) {c=n;}void incr() {++c;}void decr() {--c;}int val() {return c;}
}
class UsaCont {public static void main(String arg[]) {
Contatore cont = new Contatore(5);cont.incr();System.out.println("valore =" + cont.val());
}}
> javac <nome_file>.java> java UsaCont
39
Compilazione in Java
� Una unità di compilazione è un file .java che contiene delledefinizioni di classi.
� Al massimo una di queste classi può essere public: inquesto caso deve avere lo stesso nome del file (senza.java).
� Il compilatore produce un file .class per ogni classe nel file.
� L'interprete ha la responsabilità di caricare e interpretarequesti file.
40
Riuso del software:Ereditarieta`,Composizione,Polimorfismo eBinding Dinamico
41
Ereditarietà
� Meccanismo per lo sviluppo incrementale di programmi
� Consente di estendere classi preesistenti aggiungendo omodificando componenti (variabili o metodi)
42
Ereditarietà
� Data la classe di sopra vogliamo estendere la finestra aggiungendo untitolo
class Finestra { Rettangolo r; .... void disegnaCornice() {...} void disegnaContenuto() {...}}
class FinestraConTitolo extends Finestra { String titolo; void disegnaTitolo() {...}}
43
Sottoclassi
� FinestraConTitolo è unasottoclasse di Finestra.
� Una sottoclasse ereditatutte le variabili ed i metodidella sopraclasse.
44
Ereditarietà� Gli oggetti della classe Finestra sono costituiti da
� Gli oggetti della classe FinestraConTitolo sonocostituiti da
variabili Rettangolo r;metodi void disegnaCornice() {...} void disegnaContenuto() {...}
variabili Rettangolo r; String titolo;metodi void disegnaCornice() {...} void disegnaContenuto() {...}
void disegnaTitolo() {...}
45
Extends (Java)
� E` la parola chiave per definire una gerarchia di classi
class ClassePadre {[…]}
class ClasseFigliaUno extends ClassePadre {[…]}class ClasseFigliaDue extends ClassePadre {[…]}
ClassePadre
ClasseFigliaUno ClasseFigliaDue
Ereditarieta`
46
Extends (Java)
� Superclasse, classe base, classe padre� Sottoclasse, classe derivata, classe figlia
� Le sottoclasse hanno le funzionalita` delle propriesopraclassi piu` altre specifiche
� Specializzazione� Un elemento di una sottoclasse e` anche un elemento di
una sua sopraclasse
class B extends Ax ∈∈∈∈ B ⇒⇒⇒⇒ x ∈∈∈∈ A
A
BA
B
47
Controllo statico dei tipi
� Java, come molti altri linguaggi, effettua un controllo dei tipi(type checking) statico.
� Statico: fatto dal compilatore prima di iniziare l'esecuzionedel programma.
� Dinamico: fatto dall'interprete durante l'esecuzione (aruntime)
� Il type checking statico garantisce che non ci sarannoerrori durante l'esecuzione.
48
Controllo statico dei tipi
� Type checking statico: il compilatore controlla che per unavariabile si chiami un metodo definito per la classe diquella variabile.
Finestra f;FinestraConTitolo ft;...ft.disegnaCornice(); f.disegnaCornice();ft.disegnaTitolo(); f.disegnaTitolo();
errore di compilazionef è una finestra e non ha ilmetodo disegnaTitolo
corretto
49
Tassonomie
� Spesso l'ereditarietà è utilizzata per rappresentaretassonomie (classificazioni)
50
Sottotipi
� Una sottoclasse può essere vista come l'implementazione di unsottotipo.
� L'ereditarietà realizza una relazione is-a (è un).
� Un rettangolo è un poligono.
� Un rettangolo ha tutte le operazioni di poligono (eventualmenteridefinite) più altre operazioni specifiche.
51
Ereditarietà singola� Ogni sottoclasse ha una
sola sopraclasse.� Struttura ad albero.
� In Java la classe Object èla radice della gerarchia.
� Qualunque oggetto è unObject.
� I tipi primitivi non sonoObject.
52
Ereditarietà multipla
� In Java non è permessa.� Dà maggiore espressività ma crea problemi di conflitti e duplicazioni.
ApparecchioElettrico tensione potenza
Articolo codice prezzo
Televisore pollici
53
Polimorfismo� POLIMORFISMO: proprietà di un
oggetto di avere più di un tipo, inaccordo alla relazione diereditarietà.
Esempio:� D sottoclasse di B e di A� un oggetto D è un B ed è un A� un oggetto di tipo (classe) D è
anche un oggetto di tipo (classe) Be anche un oggetto di tipo (classe)A
54
Polimorfismo
A a; B b; D d;d = new D();b = new D();a = new D();a = b;
questiassegnamentisono tutti legaliperché unoggetto di tipo Dha anche tipo Be A
55
Polimorfismo
� L'assegnamento x = espr è legale per il compilatore se:� A uguale a B� B sottoclasse (sottotipo) di A
dove A è il tipo di x e B è il tipo di espr
� Analogamente se x è un parametro formale di un metodo eespr è il parametro attuale (della chiamata)
� Controllo statico.
56
Upcasting
� Upcasting: ci si muove da un tipo specifico ad uno piùgenerico (da un tipo ad un suo “sopratipo”).
� L’upcasting è sicuro per il type checking: dato che unasottoclasse eredita tutti i metodi delle sue sopraclassi, ognimessaggio che può essere inviato ad una sopraclasse puòanche essere inviato alla sottoclasse senza il rischio dierrori durante l'esecuzione.
A a; B b; D d;d = new D();
b = d;
a = d;
d viene visto come se fosse un oggetto di tipo B
d viene visto come se fosse un oggetto di tipo A
57
Upcasting
Poligono p;Rettangolo r;...p.disegna();r.disegna();p.perimetro();r.perimetro();
corretto per ilcompilatore
58
Upcasting
Poligono p;Rettangolo r;...r.diagonale();
p.diagonale();
errore dicompilazionep è di tipo Poligonoe non ha il metododiagonale
corretto
59
Upcasting Poligono p;Rettangolo r;...p = r;r.diagonale();p.diagonale();
Il compilatore dà errore ma, se si facesse ilcontrollo a runtime, p.diagonale()sarebbe corretto perché p è legata ad unrettangolo (che possiede il metododiagonale).
Visto da p, il rettangolo è un poligono.
p
r
Rettangolo
60
Upcasting
Poligono p;Rettangolo r;p = r;r.diagonale();
p.diagonale();
errore dicompilazionep è di tipo Poligonoe non ha il metododiagonale
corretto
se si facesse il controllo a runtime,sarebbe corretto perché p è legata ad unrettangolo (che possiede il metododiagonale).
61
Overriding� Una sottoclasse può anche ridefinire (OVERRIDING) un metodo della
sopraclasse.
class Finestra { Rettangolo r; .... void disegnaCornice() {...} void disegnaContenuto() {...}}
class FinestraConTitolo extends Finestra { String titolo; void disegnaCornice() { … disegna la cornice con il titolo …}}
62
Cella (1)
class Cella { int contenuto=0; int get() {return contenuto;} void set(int n) {contenuto=n;}}
class CellaConMemoria extends Cella { int backup=0; void set(int n) {backup=contenuto; contenuto=n;} void restore() {contenuto=backup;}}
63
Ereditarietà da Object (Java)class Complex { double re,im; ...}
Complex c = new Complex(1.5, 2.4);System.out.println(c);
c viene convertito in stringa con ilmetodo toString definito in Object.Si ottiene: [email protected] può ridefinite toString
class Complex { ... String toString() { return(re + " + i " + im); }}
Con la stampa si ottiene: 1.5 + i 2.4
64
Come estendere un metodo
� Spesso un metodo di una sottoclasse definito peroverriding non ridefinisce completamente il metodo con lostesso nome della sua sopraclasse, ma lo estende.
� Ad esempio, il metodo disegnaCornice dellaFinestraConTitolo estende il metodo disegnaCornice dellaFinestra, con del codice specifico per disegnare il titolo.
� Per evitare di duplicare il codice, si può far riferimento adun metodo della sopraclasse con lo stesso nome mediantela notazione super.
65
superPer ridefinire un metodo in modo incrementale:
class FinestraConTitolo extends Finestra { String titolo; void disegnaCornice() { super.disegnaCornice(); ... nuovo codice ... }}
super.disegnaCornice() chiama il metododisegnaCornice della sopraclasse (che altrimenti nonsarebbe visibile).
66
Cella (2)
class Cella { int contenuto=0; int get() {return contenuto;} void set(int n) {contenuto=n;}}
class CellaConMemoria extends Cella { int backup=0; void set(int n) {backup=contenuto; super.set(n);} void restore() {contenuto=backup;}}
67
Super come costruttore della sopraclasse� Super è utilizzata
per chiamare uncostruttore dellasopraclasse
� La chiamata dithis(… ) o super(…)deve essere la primaistruzione delcostruttore!
� Se è omessa lachiamata di uncostruttore sellasopraclasse vienesempre chiamatoper super()
class ClasseSopra { public ClasseSopra(int x) { System.out.println("Costruttore ClasseSopra: " + x); } public ClasseSopra() { this(-1); System.out.println("Costruttore ClasseSopra"); }}
class ClasseSotto extends ClasseSopra { public ClasseSotto (int x) { super(x); System.out.println("Costruttore ClasseSotto"); } public ClasseSotto() { super()super();; System.out.println("ostruttore ClasseSotto"); }}
68
UpcastingPoligono p;Rettangolo r;...p = r;p.disegna();
p.perimetro();
corretto per il compilatore,maquale metodo si esegue?
Quello di Poligono oquello di Rettangolo?
69
Binding dinamico
� Un oggetto decide quale metodo applicare a se stesso inbase alla propria posizione nella gerarchia dell’ereditarieta`
� Binding dinamico: decidere a tempo di esecuzione qualemetodo applicare
� Binding statico: decidere a tempo di compilazione qualefunzione applicare (Pascal, C, …)
Java adotta il binding dinamico
70
Binding dinamicop.perimetro();
Si esegue il metodo perimetro dell'oggetto a cui p fa riferimento inquel momento.
Poligono p = new Poligono();Rettangolo r = new Rettangolo();
p.perimetro();
p = r;
p.perimetro();
si esegue il metodoperimetro di Poligono
si esegue il metodoperimetro di Rettangolo
71
Binding dinamico� In questo contesto:
� Binding: legame fra il nome di un metodo in unainvocazione e (codice del) metodo.
� obj.m(): quale metodo m viene eseguito?
� Nei linguaggi tradizionali le chiamate di procedura vengonorisolte dal compilatore.
� Nei linguaggi ad oggetti (tranne il C++) le chiamate dimetodi sono risolte dinamicamente.
� BINDING DINAMICO: la forma di un oggetto determinadinamicamente quale versione di un metodo applicare.
72
Binding dinamicoclass Finestra { Rettangolo r; .... void disegnaCornice() {...} void disegnaContenuto() {...} void rinfresca() { this.disegnaCornice(); this.disegnaContenuto(); }}
class FinestraConTitolo extends Finestra { String titolo; void disegnaCornice() { … disegna la cornice con il titolo …}}
73
Binding dinamicovoid rinfresca() { this.disegnaCornice(); this.disegnaContenuto(); }
this (che può anche essere omesso) siriferisce sempre all’oggetto corrente.
FinestraConTitolo ft;...ft.rinfresca();
chiama il metodo disegnaCornice diFinestraConTitolo
74
OverridingRicerca di un metodo per un oggetto:� la sottoclasse verifica se possiede o meno un metodo con
tale nome e con gli stessi parametri (stessa signature), sesi`, lo usa
� se no, la classe padre cerca per la classe figlia tale metodotra quelli in essa definiti (e cosi` via nella gerarchia)
� Un metodo definito in una sottoclasse e avente la stessasignature di un metodo di una delle classi antenatenasconde il metodo di quest’ultima alla sottoclasse
75
Overloading, overriding, …� Firma o
signature: nome+ lista dei tipi deiparametri
� Overloading:stesso nome madiversa lista deitipi di parametri
� Overriding:stessa firma maclassi diverse(purché nellastessagerarchia)
class ClasseA { public void metodo (int x) { System.out.println("Metodo di Classe A: " + x); } public void metodo() { System.out.println("Metodo di Classe A"); this.metodo(-1); }}
class ClasseB extends ClasseA { public void metodo (int x) { System.out.println("Metodo di Classe B esteso"); super.metodo(x); } public void metodo() { System.out.println("Metodo di Classe B esteso"); super.metodo(); }}
OVERLOADING
OVERLOADING
OVERRIDING OVERLOADING
76
Overriding di metodi privati� Se invio il messaggio metodo1
ad un oggetto di tipo ClasseDuequale metodo metodo2 vieneeseguito?
� Binding dinamico?
� Dichiarare che un metodo èprivato equivale a “cambiarglinome”
� In effetti a parte ClasseUnonessuno sa o deve saperedell’esistenza di metodo2 diClasseUno
class ClasseUno { public void metodo1 () { System.out.println("Eseguito metodo 1 nella classe Uno"); this.metodo2(); } private void metodo2() { System.out.println("Eseguito metodo 2 nella classe Uno"); }}
class ClasseDue extends ClasseUno { public void metodo2 () { System.out.println("Eseguito metodo 2 nella classe Due"); }}
77
Overriding di campi
� È possibile ridefinire deicampi
MA
� Ai campi non si applica ilbinding dinamico!
class ClassePadre { public int x = 1; public int y = 2; public void getValue() { System.out.println("Valore della x: " + this.x); System.out.println("Valore della y: ” + this.y); }}
class ClasseFiglia extends ClassePadre { public String x = “3”; public int z = 4; public void getValue() { super.getValue(); System.out.println("Valore della x estesa: " + this.x); System.out.println("Valore della z: ” + this.z); }}
78
Overriding di variabili nei blocchi� È possibile definire variabili
locali ad un blocco
MA
� A differenza del C o delPascal, in un blocco internoJava non è possibile ridefinireuna variabile esterna
class ProvaVariabiliLocali{ public static void main(String[] args) { { int z = 2; } System.out.println(z); int x = 1; if (x > 0) { int y = 3; } else { int x = 2; int y = 5; } int y = 4; }}
79
Riuso del software� La programmazione ad oggetti consente di utilizzare classi
già esistenti per produrre nuovo software:
� Uso.� Un oggetto comunica con oggetti di altre classi
� Composizione.� Si definiscono nuove classi i cui oggetti sono composti di
oggetti di classi già esistenti.� Ereditarietà.
� Favorisce lo sviluppo incrementale, estendendo classi giàesistenti.
80
Composizioneclass Automobile { int lunghezza; Motore motore; Ruota[] ruote; ...}
class Motore { int cilindrata; ...}
Automobile miaAuto = new Automobile();...miaAuto.motore.cilindratamiaAuto.ruote[1].pressione
class Ruota { double pressione; int diametro; ...}
81
Ereditarietà vs composizioneAppElettr Articolo
Televisore
Televisore è un apparecchioelettrico e è un articolo.La sottoclasse eredita ilcomportamento di altre classi.
Automobile
Motore Ruote
Carrozzeria
L'automobile ha un motore, unacarrozzeria, …
L'automobile non ha ilcomportamento del motore, ...
82
Programmare con l'ereditarietà� Si consideri una figura composta
di diverse forme geometriche(linee, rettangoli, cerchi, …).
� Nella programmazionetradizionale, una procedura perdisegnare la figura dovrebbeconsiderare tutti i casi.
� Se si aggiunge la formaTRIANGOLO occorre modificarela procedura disegna.
void disegna(figura f) { for ogni forma S in f switch(S.genere) case LINEA:
disegnaLinea() case RETTANGOLO:
disegnaRettangolo() case CERCHIO:
disegnaCerchio()…}
83
Programmare con l'ereditarietà
class Figura { Forma[] s; //una figura è inplementata //come un array di Forme void disegnaFigura() { for (int i=0; i<s.length; i++) s[i].disegna(); }...
84
Programmare con l'ereditarietà
� Se si aggiunge la forma Triangolo, è sufficiente definire unanuova sottoclasse di Forma con il metodo disegna:
� La classe Figura non viene modificata.
� Il binding dinamico fa sì che, se la figura contiene untriangolo, venga chiamato il metodo per disegnare untriangolo.
class Triangolo extends Forma { ... void disegna(){...} }
85
Classi astratte
� In un programma non ci si aspetta di chiamare il metododisegna della classe Forma, né di usare oggetti di questaclasse.
� La classe Forma serve solo per avere una interfacciacomune per le varie forme specifiche.
86
Classi astratte
abstract class Forma { abstract void disegna();}
class Linea extends Forma { void disegna() { ......}}
....Forma f = new Forma();
Forma f = new Linea();
f.disegna();
Errore di compilazione.Non si possono creare og-getti di una classe astratta.
Non c'è la implementa-zione del metodo
Alcuni metodi (dichiarati abstract) non sono implementati
87
Es.: Poligoni� perimetro, area sono
piu` volte ridefinitenella gerarchia diclasse
88
Es.: Prisma� I metodi volume,
superficieLaterale eSuperficieTotalesono polimorfi
89
Interfacce
� Una classe astratta pura costituisce una interfaccia.
� In Java può essere definita anche come interface.
interface Forma { void disegna();}
class Linea implements Forma { void disegna() { ......}}...Forma f = new Linea();f.disegna();
90
Interfacce vs. classi astratte
� Le classi astratte possono essere miste, ossia possonocontenere anche metodi non astratti.
� Con l'ereditarietà singola di Java, una classe può esseresottoclasse solo di una classe astratta.
� Le interfacce invece non sono soggette al vincolo dellastruttura gerarchica ad albero.
� Una classe può implementare più di una interfaccia(qualche analogia con ereditarietà multipla).
91
Interfacce multipleinterface A { void metodoA();}
interface B { void metodoB();}
class C implements A,B { void metodoA() {System.out.println("sono A");} void metodoB() {System.out.println("sono B");}
public static void main(String[] args) { A a = new C();//l’oggetto è visto come un A B b = new C();//l’oggetto è visto come un B a.metodoA(); b.metodoB(); a.metodoB(); //errore: A non ha il metodB }}
92
Classi generiche� La proprietà che tutte le classi
sono discendenti di Objectconsente di definire strutture datiche possono contenere oggettidi qualunque tipo.
� Non si può specificare il tipodegli elementi della pila:possono essere oggettiqualunque.
class Pila { ... void push(Object x) {...}; Object pop() {...};}
Pila s; Linea l; Rettangolo r;...s.push(l); s.push(r);
93
Downcasting
Supponiamo di sapere chesulla pila vengono messi solorettangoli. Come possiamoutilizzare gli oggetti estrattidalla pila?
class Pila { ... void push(Object x) {...}; Object pop() {...};}
Pila s; Rettangolo r;...s.push(new Rettangolo());
r = s.pop();Errore di compilazione.pop restituisce un Object, che èpiù generale di Rettangolo
94
Downcasting
� Downcasting: ci si muove da un tipo più generale ad unopiù specifico (da un tipo ad un sottotipo)
� Se A è un sottotipo di B e se espr ha tipo B,
(A) espr ha tipo A
� L’assegnamento
A a = (A) espr è corretto per il compilatore
� (A) espr può dare errore a run time, se l’oggetto ottenutovalutando espr non ha tipo A.
95
Downcastingclass Pila { ... void push(Object x) {...}; Object pop() {...};}
...Pila s; Rettangolo r;...s.push(new Rettangolo());
r = (Rettangolo) s.pop();
Accettato dal compilatore.Può dare errore a run time.Controllo a run-time.Quando si esegue questaistruzionesi controlla che l'oggettorestituitoda pop sia veramente unrettangolo.
Non e` un cast alla “C” !