metodi per riutilizzare programmi oo
TRANSCRIPT
I concetti della programmazione OO per
riutilizzare il codice Lezione del 27 ottobre 2008 per il modulo
“Programmazione ad Oggetti 3° parte
La riutilizzazione del codice La programmazione strutturata consente di
riutilizzare i programmi esistenti. Si può scrivere una procedura, una funzione, una
subroutine, e poi usarla tante volte quante si vuole Tuttavia nella progettazione Orientata agli
Oggetti si fa molto di più. La programmazione OO permette di definire
relazioni tra le classi degli oggetti che facilitano: non solo il riutilizzo del codice, ma anche la progettazione del medesimo con una
visione globale della sua architettura
Metodi per riutilizzare del codice nella programmazione Orientata agli Oggetti Nella programmazione OO ci sono
fondamentalmente due modi distinti per riutilizzare il codice esistente
La “Ereditarietà” che permette ad una classe di ereditare gli attributi ed i metodi di un’altra classe.
La “Composizione” che fornisce un meccanismo per costruire un oggetto composto di altri oggetti, quindi una nuova classe a partire da altre classi già esistenti
La ereditarietà Qualcuno ha creato con un
processo di astrazione una superclasse che ha attributi e metodi comuni ad un certo insieme di classi.
Ad esempio in una classe Dog ed in un’altra Cat c’è un attributo per il colore degli occhi. In un modello procedurale, il
codice per Dog, nonché quello per Cat dovrebbero entrambi contenere questo attributo
Invece in un progetto OO, l’attributo colore occhi è spostato nella superclasse Mammal (mammiferi), insieme con altri attributi comuni e metodi comuni.
In questo caso sia Dog che Cat ereditano dalla classe Mammal questo attributo eyeColor
Esempio di ereditarietà
Ciò significa che questa classe Dog ha i seguenti attributi eyeColor // ereditato dalla
classe Mammal barkFrequency // definito solo
per gli oggetti Dogs Al medesimo modo, un
oggetto Dog ha i seguenti metodi: getEyeColor() // ereditato da
Mammal bark() // definito solo
per Dog
Ciò significa che questa classe Cat ha i seguenti attributi: eyeColor // ereditato dalla
classe Mammal meowFrequency // definito
solo per gli oggetti Cats Al medesimo modo un
oggetto Cat ha i seguenti metodi: getEyeColor() // ereditato da
Mammal meow() // definito solo per Cat
Le classi Dog e Cat ereditano entrambe dalla superclasse Mammal.
Quando un oggetto Dog o Cat viene instanziato, esso contiene ogni cosa definita nella sua classe così come ogni cosa definita nella classe genitore.Pertanto essi hanno le proprietà delle loro definizione di classe e quelle ereditate dalla classe Mammal.
Superclasse e sottoclasse La superclasse, o classe genitore, contiene tutti gli
attributi ed i comportamenti che sono comuni alle classi che li ereditano.
Ad esempio, nel caso della classe Mammal, tutti i mammiferi hanno attributi simili quali colore degli occhi, colore dei capelli, così come comportamenti comuni quali generaCaloreInterno() cresceCapelli().
Tutti i mammiferi hanno questi attributi e comportamenti, pertanto non è necessario duplicarli lungo la gerarchia
della ereditarietà in ciascun tipo di mammifero. La duplicazione, oltre ad essere faticosa, introduce
errori ed inconsistenze Le classi Dog e Cat ereditano tutti questi attributi e
comportamenti comuni dalla classe Mammal. La classe Mammal è la superclasse, Dog e Cat sono le
sottoclassi o classi figlie.
Programmare per differenze (generalizzazione) (specializzazione)
Poiché la classe Dog e Cat ereditano gli attributi e i comportamenti della superclasse Mammal, queste classi specializzate devono solo implementare quegli attributi e quei comportamenti per i quali sono diverse dai mammiferi in generali.
Queste sottoclassi devono aggiungere i loro dettagli, specifici del loro essere Dog e Cat.
Per questo motivo si dice anche che le superclassi sono classi generali, mentre le sottoclassi si dicono specializzate.
Inoltre il processo di creazione della superclasse si chiama per il medesimo motivo “generalizzazione”, mentro il processo di programmazione per differenza delle sottoclassi si chiama “specializzazione”
Astrazione per ereditarietà Un albero di ereditarietà
può diventare molto grande.
Dopo che le classi Mammal, Cat e Dog sono state completate, altre classi si possono aggiungere alla gerarchia quali Lions, Tigers. Ognuna di queste può, a sua volta essere la superclasse di altre classi.
Cat può essere superclasse di GattoPersiano, GattoSiamese.
Dog può essere superclasse di GermanShepherd, di Poodle
La potenza della ereditarietà sta in quella della astrazione e della organizzazione
Esempio di albero di ereditarietà Quali sono i metodi
di GermanShepherd ?
I suoi isGerman() di Dog bark() di Mammal getEyeColor
Quali sono i metodi di Poodle ?
Relazione “is-a” Il Cerchio, il Quadrato, la
Stella ereditano direttamente da Shape
A questa relazione ci si riferisce spesso come ad una “relazione is-a”
Un cerchio “is a” shape Un quadrato è una
forma Una stella è una forma
Introduzione al polimorfismo Nelle figura shape, il nome su ciascuno degli
oggetti rappresenta il metodo “draw” (disegna) rispettivamente di Cerchio, Quadrato, Stella
Quando disegniamo una forma, indipendentemente da quale essa sia, invochiamo un metodo chiamato draw()
È responsabilità individuale dell’oggetto, che esso sia un cerchio, un quadrato oppure una stella, disegnare sé stesso
Qui sta un nuovo concetto della programmazione OO
Il polimorfismo
Il polimorfismo Polimorfismo è un termine greco che significa
“molte forme” Il polimorfismo è strettamente correlato al
concetto di ereditarietà Quando un messaggio è inviato ad un
oggetto, quell’oggetto deve avere un metodo (un’interfaccia) per rispondere a quel messaggio
In una gerarchia ereditaria, tutte le sottoclassi ereditano le interfacce delle loro superclassi
Poiché ogni sottoclasse è un’entità separata, ciascuna di esse può richiedere una distinta e diversa risposta al medesimo messaggio.
Esempio per comprendere il polimorfismo Consideriamo la classe Shape ed un suo
comportamento draw() Quando chiedete di disegnare una forma
dovete specificare quale forma. nessuno può disegnare una forma (Shape) perché
Shape è un concetto astratto In effetti il metodo draw() di Shape non ha neanche
un’implementazione Per disegnare una forma occorre specificare
una forma concreta (cerchio, quadrato, stella) Per fare questo dovete fornire l’effettiva
implementazione del metodo draw() in Cerchio, Quadrato, Stella.
Sovrascrittura (overriding) di un metodo Anche se la classe Shape ha un metodo
draw(), nelle classi Cerchio, Quadrato, Stella scriviamo il metodo draw() sovrascrivendo il metodo draw() ereditato da Shape.
Sovrascrivere significa riscrivere e rimpiazzare in una sottoclasse l’implementazione di un metodo ereditata dalla superclasse
Esempio di sovrascrittura di un metodo Ad esempio supponiamo di avere una
collezione di tre forme geometriche: cerchio, quadrato, stella
Anche se le trattiamo tutte come forme geometriche e gli inviamo il medesimo messaggio draw() Il risultato finale di ciascun disegno è diverso perché
in ciascuna delle classi di questi oggetti abbiamo fornito una concreta implementazione di questo metodo draw() riscrivendolo
Pertanto ciascuna classe pur sollecitata dal medesimo messaggio è in grado di rispondere differentemente
Questo è il polimorfismo !!!!
Un po’ di codice per esempio public abstract class Shape{
public abstract void draw();
} public class Cerchio{
public void draw(){ System.out.println(“Cerchio!!”);
} }
public class Quadrato{ public void draw(){ System.out.println(“Quadrato!!”);
} }
public class Stella{ public void draw(){ System.out.println(“Stella!!”);
} }
Instanziamo qualche oggetto c1=new Cerchio(); q1=new Quadrato(); s1=new Stella();
Inviamo il medesimo messaggio a tutti questi oggetti c1.draw(); q1.draw(); s1.draw();
L’effettiva risposta dipende dal tipo di oggetto
Ma abbiamo inviato a tutti il medesimo messaggio !!
Il concetto chiave è che stiamo inviando il medesimo messaggio alle classi Shape e sperimentiamo diverse risposte a seconda di quale sottoclasse di Shape è utilizzata !
Questo è il polimorfismo !
La composizione È naturale pensare agli oggetti come aggregati
di altri oggetti Un computer contiene una scheda madre, una
scheda video, una tastiera, un disco rigido. Anche se il computer è considerato come un
oggetto unico, anche l’unità disco è un oggetto valido
Infatti potreste aprire il computer e rimuovere il disco rigido e prenderlo in mano
Gli oggetti quindi sono spesso costruiti o composti da altri oggetti
Questa è la composizione
L’astrazione della composizione Anche la composizione
fornisce un meccanismo per costruire gli oggetti, includendo delle classi all’interno di altre classi
Come si fa ? Consideriamo la relazione
tra un automobile e il suo motore
Possiamo dire che l’auto contiene il motore
Ma non possiamo dire che un’auto è un motore !
Piuttosto usiamo il termine l’auto “has a” ha un motore
public class Motore { } public class Auto {
private Motore m;…
}
In questo modo siamo in grado di includere un oggetto all’interno di un altro oggetto che lo contiene
In pratica definiamo un nuovo tipo di variabile che rappresenta l’oggetto che vogliamo includere
La relazione “has a” La relazione di ereditarietà è considerata una
relazione del tipo “è un” (is-a) Invece la relazione di composizione è
considerata del tipo ha un (has-a) Quindi il computer ha un disco rigido Un computer non è un disco rigido quindi tra
computer e disco rigido non c’è una relazione di ereditarietà, ma invece c’è una relazione di composizione