Ereditarietà Ereditarietà: concetti di base

Programmazione ad Oggetti con Java: Ereditarietà
Ereditarietà
Ereditarietà: concetti di base

L’ereditarietà è uno dei concetti base della
programmazione ad oggetti

Concetto di base:

l’ereditarietà permette di usare una classe precedentemente
definita per la definizione di una nuova
L’ereditarietà è una tecnica tale per cui è possibile
definire:



2
una classe estremamente generale
successivamente classi più specializzate semplicemente
aggiungendo nuovi dettagli alla classe di partenza
Programmazione ad Oggetti con Java: Ereditarietà
1
Programmazione ad Oggetti con Java: Ereditarietà
Ereditarietà: definizione più formale
È una relazione fra classi in cui una classe (superclasse o
classe base) “raccoglie a fattor comune” le caratteristiche
comuni di una o più altre classi (sottoclassi o
specializzazioni)
Le sottoclassi ereditano tutte le caratteristiche della
superclasse
In UML si indica graficamente con una freccia dalla
sottoclasse alla superclasse



VeicoloMotorizzato
superclasse o classe base
Auto
Moto
Pulman
sottoclassi o specializzazioni
3
Programmazione ad Oggetti con Java: Ereditarietà
Astrazione
Superclassi
Specializzazione
Generalizzazione
Classi
Classificazione
Istanziazione
Oggetti
Rappresentazione
Mondo reale
4
Programmazione ad Oggetti con Java: Ereditarietà
2
Programmazione ad Oggetti con Java: Ereditarietà
Perché l’Ereditarietà
Economia


tutti gli attributi, operazioni e associazioni comuni a un certo insieme di
classi vengono scritte una sola volta
Consistenza


se un attributo, operazione o associazione della superclasse viene
cambiato, la modifica si ripercuote automaticamente su tutte le sottoclassi
Riuso


la superclasse può essere riusata in contesti diversi
Estendibilità



è sempre possibile, anche in un secondo momento, aggiungere nuove
sottoclassi senza dover riscrivere la parte comune contenuta nella
superclasse
ogni sottoclasse può ridefinire a piacimento attributi e operazioni
(overriding)
5
Programmazione ad Oggetti con Java: Ereditarietà
Fino a dove posso arrivare?
Non ho limiti sulla gerarchia che posso costruire

Veicolo
VeicoloMotorizzato
Auto
Moto
VeicoloNonMotorizzato
Pulman
Bicicletta
Carrozza
Taxi
6
Programmazione ad Oggetti con Java: Ereditarietà
3
Programmazione ad Oggetti con Java: Ereditarietà
Il tipo di relazione

L’ereditarietà realizza una relazione is-a

Quindi è corretto affermare che un oggetto creato a
partire da una sottoclasse sia di tipo della superclasse!

Esempi:



un oggetto istanziato a partire dalla classe Bicicletta, oltre
che essere una Bicicletta, è anche un
VeicoloNonMotorizzato e un Veicolo
un oggetto istanziato a partire dalla classe Taxi, oltre che ad
essere un Taxi, è anche un’Automobile, un
VeicoloMotorizzato e un Veicolo
...
7
Programmazione ad Oggetti con Java: Ereditarietà
Ereditarietà multipla
Una classe può ereditare da più superclassi (ereditarietà
multipla)
Esempio:



lo studente lavoratore...
Studente
-
Lav oratore
nome: String
cognome: String
matricola: int
-
nome: String
cognome: String
numeroPrevidenza: int
StudenteLav oratore
8
Programmazione ad Oggetti con Java: Ereditarietà
4
Programmazione ad Oggetti con Java: Ereditarietà
Ereditarietà multipla: problemi
L’ereditarietà multipla è
semplice concettualmente, ma
porta a una serie di problemi
tecnici:



Cosa succede se una classe
eredita due volte dalla stessa
superclasse?
Cosa succede se due superclassi
diverse hanno un attributo con lo
stesso nome?
Persona
-
nome: String
cognome: String
Studente
-
Lav oratore
matricola: int
-
numeroPrevidenza: int
StudenteLav oratore
Fortunatamente Java non
supporta l’ereditarietà multipla

9
Programmazione ad Oggetti con Java: Ereditarietà
L’Ereditarietà in Java

La sintassi utilizzata in Java per esplicitare che una classe
deriva da un’altra è la seguente:
public class ClassePadre {
...
}
public class ClasseFiglia extends ClassePadre {
...
}
10
Programmazione ad Oggetti con Java: Ereditarietà
5
Programmazione ad Oggetti con Java: Ereditarietà
Esempio

Proviamo ad implementare il seguente
diagramma di classi


Persona
Creiamo un’altra classe con main in cui:




nessun costruttore e metodo toString()
creiamo una persona con nome Mario,
cognome Rossi
creiamo uno studente con nome Marco,
cognome Verdi e matricola 123456
stampiamo lo stato degli oggetti
-
nome: String
cognome: String
+
+
+
+
setNome(nome :String) : void
setCognome(cognome :String) : void
getNome() : String
getCognome() : String
Studente
-
matricola: int
+
+
setMatricola(matricola :int) : void
getMatricola() : int
Sorgente ...
11
Programmazione ad Oggetti con Java: Ereditarietà
La classe Object

In Java qualsiasi classe specializza la classe
Object
Obj ect
+
+

Fino ad ora, non sapendolo, abbiamo
scritto classi che sono specializzazione
della classe Object


quindi qualsiasi metodo ed attributo definito
nella classe Object è ereditato dalle
sottoclassi
equals(object :Object) : boolean
toString() : String
Persona
-
nome: String
cognome: String
+
+
+
+
setNome(nome :String) : void
setCognome(cognome :String) : void
getNome() : String
getCognome() : String
Alcuni metodi importanti della classe
Object:
-
matricola: int

+
+
setMatricola(matricola :int) : void
getMatricola() : int

12
public boolean equals(Object o)
public String toString()
Studente
Programmazione ad Oggetti con Java: Ereditarietà
6
Programmazione ad Oggetti con Java: Ereditarietà
Esempio

Se modifichiamo il main
dell’esercizio della slide 12
nel modo seguente:

... Non avremo errori di
compilazione:


public class Test {
public static void main(String a[]) {
Persona p = new Persona();
p.setNome("Mario");
p.setCognome("Rossi");
su oggetti di tipo Persona è
possibile invocare il metodo
toString() poiché
ereditato dalla classe Object
Studente s = new Studente();
s.setNome("Marco");
s.setCognome("Verdi");
s.setMatricola(123456);
System.out.println("Persona "+
p.getNome() + " " + p.getCognome());
System.out.println("Studente "+
s.getNome() + " " + s.getCognome() +
" " + s.getMatricola());
System.out.println(p.toString());
Output del tipo:
}
NomeClasse@hashCode }
13
Programmazione ad Oggetti con Java: Ereditarietà
Visibilità

Quando una classe ne specializza un’altra, eredita tutto a prescidere dalla
visibità!

Però:


se un attributo è definito private nella superclasse non sarà accessibile
tramite nome!
 occorrerà passare attraverso metodi (ovviamente non privati!)
se un metodo è definito private nella superclasse, non ci sarà alcun modo per
permettere alle sottoclassi di invocarlo

Se le sottoclassi hanno la necessità di accedere in modo diretto ad attributi
e/o metodi definiti nella superclasse devo utilizzare un’altro tipo di visibilità:
protected

Esempio: Auto + Taxi
14
Programmazione ad Oggetti con Java: Ereditarietà
7
Programmazione ad Oggetti con Java: Ereditarietà
Esempio
package a
Accede direttamente a:
x, y, w, z
A
#
~
+
Accede direttamente a:
y, w, z
x:
y:
z:
w:
int
int
int
int
Accede direttamente a:
y, w
B
Su istanze di tipo
B,
accede direttamente
a: y, w, z
Esempio:
C
1
1
D
B b;
...
b.y;
b.w;
b.z;
E
Su istanze di tipo
C,
accede direttamente
a: w
Esempio:
C c;
...
c.w;
package b
15
Programmazione ad Oggetti con Java: Ereditarietà
Riepilogo sulle visibilità

Il modificatore di visibilità si applica ad attributi e metodi
con lo stesso significato:
Visibilità
Chi può accedere
public
la classe in cui è definito
tutte le classi (sottoclassi, le classi in associazione,
classi nello stesso package, classi in package diversi)
protected
la classe in cui è definito
le sottoclassi
le classi appartenenti allo stesso package
private
la classe in cui è definito
le classi appartenenti allo stesso package
16
Programmazione ad Oggetti con Java: Ereditarietà
8
Programmazione ad Oggetti con Java: Ereditarietà
Costruttori

Cosa succede per i costruttori che accettano in ingresso
parametri?

Regola da rispettare: ogni classe inizializza i propri attributi!

ritornando all’esempio della Persona e della classe Studente



ma uno studente è caratterizzato anche dal possedere un nome e un
cognome dal momento che è una specializzazione della classe
Persona


il/i costruttori della classe Persona inizializzeranno gli attributi nome e
cognome
il/i costruttori della classe Studente inizializzeranno l’attributo
matricola
quindi, quando si crea uno studente, occorre inizializzare anche nome e
cognome
Come si fa?
17
Programmazione ad Oggetti con Java: Ereditarietà
Costruttori

Esistono 2 modi:

Meno elegante:


Più elegante:



nel/nei costruttori della sottoclasse si inizializzno i valori per tutti gli
attributi
si invoca il costruttore della superclasse passando come argomenti i
valori per gli attributi li definiti
per fare ciò si utilizza la keyword super
L’invocazione al costruttore della superclasse deve essere la
prima istruzione ad essere eseguita

18
quindi non ci possono essere contemporaneamente super e this
Programmazione ad Oggetti con Java: Ereditarietà
9
Programmazione ad Oggetti con Java: Ereditarietà
Regole

Sono sempre obbligato ad invocare esplicitamente il
costruttore della superclasse?



No: se la superclasse esporta il costruttore di default
Si: se la superclasse esporta esclusivamente costruttori con
parametri
Anche se io non invoco esplicitamente il costruttore della
superclasse, Java inserisce all’interno dei costruttori
definiti nella sottoclasse l’invocazione al costruttore di
default della superclasse


ciò comporta che il primo costruttore ad essere eseguito è
sempre quello della classe Object
ciò è valido se il costruttore non ha l’invocazione this!
19
Programmazione ad Oggetti con Java: Ereditarietà
Implementazione relazione is-a

Ricordandoci che l’ereditarietà realizza una relazione is-a,
è lecito scrivere:
SuperClasse ref = new SottoClasse();

Ma non è lecito scrivere:
SottoClasse ref = new SuperClasse();
20
Programmazione ad Oggetti con Java: Ereditarietà
10
Programmazione ad Oggetti con Java: Ereditarietà
Esempi
Ok Persona s1 = new Studente();
Studente s3 = new Persona();
Ok Object s2 = new Studente();
Ok Object p1 = new Persona();
Ok s1.setNome(“Paperone”);
s2.setCognome(“De Paperoni”);
Ok p1.toString();
21
Programmazione ad Oggetti con Java: Ereditarietà
Ancora un esempio

Realizziamo il seguente diagramma di classi:
Animale
- String nome
+ Animale()
+ void dormi()
+ void mangia()


Gatto
Papera
Cane
+ Gatto()
+ void faiLeFusa()
+ void parla()
+ Papera()
+ void parla()
+ Cane()
+ void ringhia()
+ void parla()
Creiamo una classe in cui definiamo un array di 3 animali ed inseriamo un
gatto, un cane ed una papera
Per ciascuno di essi invochiamo rispettivamente: dormi, parla e mangia
22
Programmazione ad Oggetti con Java: Ereditarietà
11
Programmazione ad Oggetti con Java: Ereditarietà
Il cast


Permette di convertire un reference ad un tipo inferiore
in gerarchia di parentela
Sintassi:
NomeClasseFiglia ref2 = (NomeClasseFiglia)ref1;

Esempio:
Animale a = new Gatto(“Miguel”);
...
Gatto g = (Gatto)a;
g.faiLeFusa();

Meglio se si effettua il controllo prima:
if (a instanceof Gatto) {
Gatto g = (Gatto)a;
g.faiLeFusa();
}
23
Programmazione ad Oggetti con Java: Ereditarietà
Concetti avanzati: classi astratte

Una classe può essere astratta

questo significa che non corrisponde a un concetto concreto del
dominio applicativo, ma che è fatta apposta per funzionare da
superclasse

esempio: non esiste un veicolo, esiste un auto, una moto, ...

Un classe astratta:




non può essere instanziata
ha senso solo in quanto ne vengono create delle sottoclassi
Una classe deve essere dichiarata astratta se definisce almeno
un metodo astratto
Una classe può essere dichiarata astratta anche se non
definisce metodi astratti
24
Programmazione ad Oggetti con Java: Ereditarietà
12
Programmazione ad Oggetti con Java: Ereditarietà
Sintassi

Classe astratta
public abstract class NomeClasse {
...
}

Metodo astratto:
[mod. visibilità] abstract void nomeMetodo([parametri]);
25
Programmazione ad Oggetti con Java: Ereditarietà
L’abstract si propaga

Sono costretta a definire astratte anche le sottoclassi che
non definiscono il comportamento di metodi astratti
ereditati
Animale

- String nome
Esempio:
26
+ Animale()
+ void dormi()
+ void mangia()
+ void parla()
Felino
Papera
Cane
+ Felino()
+ Papera()
+ Cane()
+ void ringhia()
Leone
Gatto
+ Leone()
+ Gatto()
+ void faiLeFusa()
Programmazione ad Oggetti con Java: Ereditarietà
13
Programmazione ad Oggetti con Java: Ereditarietà
L’ereditarietà multipla?

Effettivamente in java la si realizza grazie all’utilizzo delle
interface

L’interface realizza quasi un’associazione del tipo “is-a”



al test instanceof restituisce true o false
Le interface contengono solo intestazioni di metodi e al
più definizioni di costanti
Sintassi: public interface NomeInterface {
// definizione nomi metodi
}
public class Classe implements NomeInterface {
// definizione del corpo dei metodi ereditati
}
27

Programmazione ad Oggetti con Java: Ereditarietà
Esempi di ereditarietà:

28
Slide successiva: equals
Programmazione ad Oggetti con Java: Ereditarietà
14
Programmazione ad Oggetti con Java: Ereditarietà
Confrontare lo stato di 2 oggetti

L’operatore == applicato a 2 reference permette di
testare se essi referenziano lo stesso oggetto


Ma se volessi sapere se due oggetti si trovano nello
stesso stato, come faccio?
effettuo una comparazione fra i valori degli attributi

Modalità classica:


29
overridare il metodo equals della classe Object
intestazione: public boolean equals(NomeClasse obj)
Programmazione ad Oggetti con Java: Ereditarietà
15