© M. Badella G. Malnati L. Tessitore, 2003-05
Ereditarietà
e
polimorfismo
Programmazione
ad Oggetti
A.A. 2004-05
© M. Badella G. Malnati L. Tessitore, 2003-05
Argomenti della lezione
I concetti principali
Ereditarietà in Java
La classe Object
Classi astratte
e interfacce
Programmazione ad Oggetti
2
© M. Badella G. Malnati L. Tessitore, 2003-05
Riusare il software
A volte si incontrano classi con funzionalità simili
In quanto sottendono concetti semanticamente “vicini”
Una mountain bike assomiglia ad una bicicletta tradizionale
È possibile creare classi disgiunte replicando le
porzione di stato/comportamento condivise
L’approccio “Taglia&Incolla”, però, non è una strategia
vincente
Difficoltà di manutenzione correttiva e perfettiva
Meglio “specializzare” codice funzionante
Sostituendo il minimo necessario
Programmazione ad Oggetti
3
© M. Badella G. Malnati L. Tessitore, 2003-05
Ereditarietà
Meccanismo per definire una nuova classe (classe
derivata) come specializzazione di un’altra (classe
base)
La classe base modella un concetto generico
La classe derivata modella un concetto più specifico
La classe derivata:
Dispone di tutte le funzionalità (attributi e metodi) di quella
base
Può aggiungere funzionalità proprie
Può ridefinirne il funzionamento di metodi esistenti
(polimorfismo)
Programmazione ad Oggetti
4
© M. Badella G. Malnati L. Tessitore, 2003-05
Esempio
Bicicletta
coppia
rapportoPosteriore
…
pedala(coppia)
cambiaRapporto(n)
frena(intensità)
…
MountainBike
rapportoAnteriore
cambiaRapportoAnt(n)
Programmazione ad Oggetti
Tandem
coppia2
pedala2(coppia)
5
© M. Badella G. Malnati L. Tessitore, 2003-05
Terminologia
Classe base,
superclasse
Bicicletta
MountainBike
Tandem
Classi derivate,
sottoclassi
Programmazione ad Oggetti
6
© M. Badella G. Malnati L. Tessitore, 2003-05
Astrazione
Il processo di analisi e progettazione del software di
solito procede per raffinamenti successivi
Spesso capita che le similitudini tra classi non siano colte
inizialmente
In una fase successiva, si coglie l’esigenza/opportunità di
introdurre un concetto più generico da cui derivare classi
specifiche
Processo di astrazione
Si introduce la superclasse che “astrae” il concetto comune
condiviso dalle diverse sottoclassi
Le sottoclassi vengono “spogliate” delle funzionalità comuni
che migrano nella superclasse
Programmazione ad Oggetti
7
© M. Badella G. Malnati L. Tessitore, 2003-05
Veicolo
double getVelocità()
double getAccelerazione()
…
Bicicletta
void pedala()
Programmazione ad Oggetti
Automobile
void avvia()
void spegni()
8
© M. Badella G. Malnati L. Tessitore, 2003-05
Tipi ed ereditarietà
Ogni classe definisce un tipo:
Un oggetto, istanza di una sotto-classe, è formalmente
compatibile con il tipo della classe base
Il contrario non è vero!
Esempio
Un’automobile è un veicolo
Un veicolo non è (necessariamente) un’automobile
La compatibilità diviene effettiva se
I metodi ridefiniti nella sotto-classe rispettano la semantica
della superclasse
L’ereditarietà gode delle proprietà transitiva
Un tandem è un veicolo (poiché è una bicicletta, che a sua
volta è un veicolo)
Programmazione ad Oggetti
9
© M. Badella G. Malnati L. Tessitore, 2003-05
Vantaggi dell’ereditarietà
Evitare la duplicazione
di codice
Permettere il riuso
di funzionalità
Semplificare la costruzione
di nuove classi
Facilitare la manutenzione
Garantire la consistenza delle interfacce
Programmazione ad Oggetti
10
© M. Badella G. Malnati L. Tessitore, 2003-05
Ereditarietà in Java
Si definisce una classe derivata attraverso la
parola chiave “extends”
Seguita dal nome della classe base
Gli oggetti della classe derivata sono, a tutti
gli effetti, estensioni della classe base
Anche nella loro rappresentazione in memoria
Programmazione ad Oggetti
11
© M. Badella G. Malnati L. Tessitore, 2003-05
Ereditarietà in Java
Veicolo.java
public class Veicolo {
private double velocità;
private double accelerazione;
public double getVelocità() {…}
public double getAccelerazione() {…}
}
public class Automobile
Automobile.java
extends Veicolo {
private boolean avviata;
public void avvia() {…}
}
Programmazione ad Oggetti
12
© M. Badella G. Malnati L. Tessitore, 2003-05
Ereditarietà in Java
Automobile a=
new Automobile();
Memoria
velocità: 0.0
accelerazione: 0.0
a
Programmazione ad Oggetti
avviata: false
13
© M. Badella G. Malnati L. Tessitore, 2003-05
Meccanismi
Costruzione di
oggetti di classi
derivate
Accesso alle
funzionalità della
superclasse
Ri-definizione di
metodi
Programmazione ad Oggetti
14
© M. Badella G. Malnati L. Tessitore, 2003-05
Costruzione
Per realizzare un’istanza di una classe
derivata, occorre – innanzi tutto – costruire
l’oggetto base
Di solito, provvede automaticamente il
compilatore, invocando – come prima operazione
di ogni costruttore della classe derivata – il
costruttore anonimo della superclasse
Si può effettuare in modo esplicito, attraverso il
costrutto super(…)
Eventuali ulteriori inizializzazioni possono essere
effettuate solo successivamente
Programmazione ad Oggetti
15
© M. Badella G. Malnati L. Tessitore, 2003-05
Esempio
class Impiegato {
String nome;
double stipendio;
Impiegato(String n) {
nome = n;
stipendio= 1500; class Funzionario
extends Impiegato {
}
}
Funzionario(String n) {
super(n);
stipendio = 2000;
}
}
Programmazione ad Oggetti
16
© M. Badella G. Malnati L. Tessitore, 2003-05
Accedere alla superclasse
L’oggetto derivato contiene tutti i
componenti (attributi e metodi) dell’oggetto
da cui deriva
Ma i suoi metodi non possono operare
direttamente su quelli definiti privati
La restrizione può essere allentata:
La super-classe può definire attributi e metodi
con visibilità “protected”
Questi sono visibili alle sottoclassi
Programmazione ad Oggetti
17
© M. Badella G. Malnati L. Tessitore, 2003-05
Ridefinire i metodi
Una sottoclasse può ridefinire metodi
presenti nella superclasse
A condizione che abbiano
Lo stesso nome
Gli stessi parametri (tipo, numero, ordine)
Lo stesso tipo di ritorno
(La stessa semantica!)
Per le istanze della sottoclasse, il nuovo
metodo nasconde l’originale
Programmazione ad Oggetti
18
© M. Badella G. Malnati L. Tessitore, 2003-05
Ridefinire i metodi
class Base {
int m() {
return 0;
}
}
class Derivata
extends Base {
int m() {
return 1;
}
}
Base b= new Base();
System.out.println(b.m());
Derivata d= new Derivata();
System.out.println(d.m());
Programmazione ad Oggetti
19
© M. Badella G. Malnati L. Tessitore, 2003-05
Ridefinire i metodi
A volte, una sottoclasse vuole “perfezionare”
un metodo ereditato, non sostituirlo in toto
Per invocare l’implementazione presente nella
super-classe, si usa il costrutto
super.<nomeMetodo> ( … )
class Base {
int m() {
return 0;
}
}
Programmazione ad Oggetti
class Derivata
extends Base {
int m() {
return super.m()+ 1;
}
}
20
© M. Badella G. Malnati L. Tessitore, 2003-05
Compatibilità formale
Un’istanza di una classe derivata è
formalmente compatibile con il tipo della
super-classe
Base b = new Derivata( );
Il tipo della variabile “b” (Base) limita le
operazioni che possono essere eseguite
sull’oggetto contenuto
Anche se questo ha una classe più specifica
(Derivata), in grado di offrire un maggior numero
di operazioni
Altrimenti viene generato un errore di
compilazione
Programmazione ad Oggetti
21
© M. Badella G. Malnati L. Tessitore, 2003-05
Compatibilità formale
C
print()
D
print()
reset()
Programmazione ad Oggetti
C v1= new C();
C v2= new D();
D v3= new D();
v1.print()
v2.print()
v2.reset()
v3.reset()
22
© M. Badella G. Malnati L. Tessitore, 2003-05
Polimorfismo
class Base {
int m() {
return 0;
}
}
class Derivata
extends Base {
int m() {
return 1;
}
}
Base b= new Derivata();
System.out.println(b.m());
Programmazione ad Oggetti
23
© M. Badella G. Malnati L. Tessitore, 2003-05
Polimorfismo
Java mantiene traccia della classe effettiva
di un dato oggetto
Seleziona sempre il metodo più specifico…
…anche se la variabile che lo contiene
appartiene ad una classe più generica!
Una variabile generica può avere “molte
forme”
Contenere oggetti di sottoclassi differenti
In caso di ridefinizione, il metodo chiamato
dipende dal tipo effettivo dell’oggetto
Programmazione ad Oggetti
24
© M. Badella G. Malnati L. Tessitore, 2003-05
Polimorfismo
Per sfruttare questa tecnica:
Si definiscono, nella super-classe, metodi con
implementazione generica…
…sostituiti, nelle sottoclassi, da implementazioni
specifiche
Si utilizzano variabili aventi come tipo quello della
super-classe
Meccanismo estremamente potente e
versatile, alla base di molti “pattern” di
programmazione
Programmazione ad Oggetti
25
© M. Badella G. Malnati L. Tessitore, 2003-05
Esempio
Forma
area()
perimetro()
Cerchio
Rettangolo
area()
perimetro()
area()
perimetro()
Programmazione ad Oggetti
Forma f1 =
new Cerchio();
Forma f2 = new
Rettangolo();
double d1,d2;
d1=f1.area();
d2=f2.area();
26
© M. Badella G. Malnati L. Tessitore, 2003-05
La classe java.lang.Object
In Java:
Gerarchia di ereditarietà semplice
Ogni classe ha una sola super-classe
Se non viene definita esplicitamente una
super-classe, il compilatore usa la classe
predefinita Object
Object non ha super-classe!
Programmazione ad Oggetti
27
© M. Badella G. Malnati L. Tessitore, 2003-05
Metodi di Object
Object definisce un certo numero di metodi
pubblici
Qualunque oggetto di qualsiasi classe li eredita
La loro implementazione base è spesso minimale
La tecnica del polimorfismo permette di ridefinirli
public boolean equals(Object o)
Restituisce “vero” se l’oggetto confrontato è identico (ha lo
stesso riferimento) a quello su cui viene invocato il metodo
Per funzionare correttamente, ogni sottoclasse deve fornire
la propria implementazione polimorfica
Programmazione ad Oggetti
28
© M. Badella G. Malnati L. Tessitore, 2003-05
Metodi di Object
public String toString()
Restituisce una rappresentazione stampabile dell’oggetto
L’implementazione base fornita indica il nome della classe
seguita dal riferimento relativo all’oggetto
(java.lang.Object@10878cd)
public int hashCode()
Restituisce un valore intero legato al contenuto dell’oggetto
Se i dati nell’oggetto cambiano, deve restituire un valore
differente
Oggetti “uguali” devono restituire lo stesso valore, oggetti
diversi possono restituire valori diversi
Utilizzato per realizzare tabelle hash
Programmazione ad Oggetti
29
© M. Badella G. Malnati L. Tessitore, 2003-05
Controllare l’ereditarietà
In alcuni casi, si vuole impedire esplicitamente
l’utilizzo della tecnica del polimorfismo
Ad esempio, per motivi di sicurezza o per garantire il
mantenimento di una data proprietà del sistema
Si utilizza la parola chiave “final”
Un metodo “final” non può essere ridefinito da una
sottoclasse
Una classe “final” non può avere sottoclassi
Un attributo “final” non può essere modificato
Non c’entra nulla con l’ereditarietà!
Programmazione ad Oggetti
30
© M. Badella G. Malnati L. Tessitore, 2003-05
Controllare l’ereditarietà
In altri casi si vuole obbligare l’utilizzo del
polimorfismo
Si introducono metodi privi di implementazione
Facendoli precedere dalla parola chiave
“abstract”
Una classe che contiene metodi astratti
Deve essere, a sua volta, dichiarata abstract
Non può essere istanziata direttamente
Occorre definire una sottoclasse che fornisca
l’implementazione dei metodi mancanti
Programmazione ad Oggetti
31
© M. Badella G. Malnati L. Tessitore, 2003-05
Classi astratte
abstract class
Base {
abstract int m();
}
class Derivata
extends Base {
int m() {
return 1;
}
}
Base b= new Derivata();
System.out.println(b.m());
Programmazione ad Oggetti
32
© M. Badella G. Malnati L. Tessitore, 2003-05
Interfacce
Una classe astratta può contenere metodi non
astratti
A beneficio delle proprie sottoclassi
In alcuni casi, si vogliono definire metodi astratti
senza vincolare la gerarchia di ereditarietà delle
classi che li implementeranno
Si utilizzano le interfacce:
Insiemi di metodi astratti e costanti (attributi static final)
Pubblici per definizione
Una classe può implementare un’interfaccia
Fornendo il codice relativo a tutti i metodi dichiarati
nell’interfaccia
Programmazione ad Oggetti
33
© M. Badella G. Malnati L. Tessitore, 2003-05
Esempio
public interface Comparable {
public int compareTo(Object o);
}
public class Rettangolo extends Forma
implements Comparable {
public int compareTo(Object o) {
//codice relativo…
}
//altri attributi e metodi…
}
Programmazione ad Oggetti
34
© M. Badella G. Malnati L. Tessitore, 2003-05
Interfacce e tipi
Analogamente alle classi, ogni interfaccia
definisce un tipo
Un oggetto che implementa una data interfaccia
ha come tipo anche il tipo dell’interfaccia
Un oggetto può implementare molte interfacce
Di conseguenza può avere molti tipi
Si può verificare se un oggetto ha un dato
tipo con l’operatore “instanceof”
if (myObject instanceof Comparable) …
Programmazione ad Oggetti
35
© M. Badella G. Malnati L. Tessitore, 2003-05
Interfacce vuote
Alcune interfacce non hanno metodi
Servono solo come “marcatori” o indicatori di
tipo
Indicano che gli oggetti delle classi che le
implementano godono di qualche proprietà
Programmazione ad Oggetti
36
© M. Badella G. Malnati L. Tessitore, 2003-05
Interfacce vuote
public interface Clonable {
//indica che è lecito usare,
// sulle istanze di questa classe
// il metodo Object.clone()
}
public class Rettangolo extends Forma
implements Comparable , Clonable {
public int compareTo(Object o) {
//codice relativo…
}
//altri attributi e metodi…
}
Programmazione ad Oggetti
37