La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

Ereditarietà e polimorfismo

Presentazioni simili


Presentazione sul tema: "Ereditarietà e polimorfismo"— Transcript della presentazione:

1 Ereditarietà e polimorfismo

2 Riusare il software Nella programmazione ad oggetti, individuata una classe, accade spesso di dover definire un’altra classe con caratteristiche simili a quella già definita In quanto sottendono concetti semanticamente “vicini” Una mountain bike, ad esempio, assomiglia ad una bicicletta tradizionale In questi casi conviene solo specificare le differenze, ovvero definire solo le proprietà e i comportamenti diversi e supporre che tutti gli altri attributi e metodi siano quelli già definiti per la prima. Nella programmazione orientata agli oggetti è possibile fare questo ricorrendo al concetto di ereditarietà.

3 Ereditarietà: in cosa consiste
L’ereditarietà permette di definire nuove classi partendo da classi sviluppate in precedenza. La nuova classe viene definita esprimendo solamente le differenze che essa possiede rispetto alla classe di partenza. L’ereditarietà permette di specificare “il punto di partenza”, cioè la classe base, e le differenze rispetto a questa.

4 Un esempio Classe Animale con proprietà:
colore degli occhi peso lunghezza numero dei sensi velocità massima Queste proprietà vanno bene per definire uccelli, pesci e mammiferi, però ce ne vorrebbero altre per definire meglio le tre sottocategorie. Gli uccelli potrebbero avere la proprietà “apertura alare”, ai pesci si potrebbe aggiungere “numero di pinne” e ai mammiferi “lunghezza del pelo”.

5 Sottoclassi e Superclassi
La nuova classe (nell’esempio Uccello, Pesce e Mammifero) viene definita sottoclasse (o classe derivata) La classe di provenienza (nell’esempio Animale) viene definita superclasse (o classe base) La sottoclasse eredita tutte le caratteristiche (attributi e metodi) della superclasse e si differenza da questa: per l’aggiunta di nuovi attributi e/o metodi per la ridefinizione di alcuni metodi della superclasse Attenzione: è vero che un pesce è un animale, non è vero il contrario in quanto un animale non è detto che sia un pesce

6 Gerarchie di classi Il concetto di ereditarietà introduce quello di gerarchia di classi. A ogni classe, infatti, possono essere associate una o più classi che la precedono immediatamente sopra nella gerarchia (le sue superclassi) e possono anche essere associate una o più classi che la seguono immediatamente sotto nella gerarchia (le sue sottoclassi). La gerarchia nasce da un processo di specializzazione. Infatti le classi che si trovano in cima alla gerarchia sono le più generali e man mano che si scende si trovano classi più specializzate

7 Gerarchie di classi CurvaChiusa Triangolo Processo di generalizzazione
Processo di specializzazione superclasse, genitrice, madre, antenata, sottoclasse, discendente, figlia, derivata Cerchio Cilindro Quadrato Rettangolo FiguraGeometrica Poligono

8 Gerarchie di classi Mezzi di trasporto Veicoli a motore
Mezzi non a motore Bicicletta Cavallo Auto Moto Autobus

9 Un altro esempio coppia rapportoPosteriore … pedala(coppia)
Bicicletta coppia rapportoPosteriore … pedala(coppia) cambiaRapporto(n) frena(intensità) Superclasse o classe base Superclasse o classe base MountainBike rapportoAnteriore cambiaRapportoAnt(n) Tandem coppia2 pedala2(coppia)

10 Ereditarietà: estensione e ridefinizione
La sottoclasse eredita dalla sopraclasse tutti gli attributi e tutti i metodi con la possibilità di inserire le differenze. La nuova classe si differenzia dalla sopraclasse in due modi: - per estensione, quando la sottoclasse aggiunge nuovi attributi e metodi che si sommano a quelli ereditati - per ridefinizione, quando la sottoclasse ridefinisce i metodi ereditati, viene cioè data un’implementazione diversa di un metodo

11 Ereditarietà in pseudocodice
In pseudolinguaggio, per creare una sottoclasse, useremo la parola chiave EREDITA e scriveremo: CLASSE <NomeSottoclasse> EREDITA <NomeSuperclasse>CerchioCilindro INIZIO ... FINE

12 Un esempio CLASSE Cilindro EREDITA Cerchio INIZIO
PUBBLICO Altezza: REALE // attributo esteso, non era in Cerchio PUBBLICO Volume(): REALE // metodo esteso RITORNO(Raggio * Raggio * Pigreco * Altezza) FINE PUBBLICO AreaLaterale(): REALE // metodo esteso PUBBLICO AreaTotale(): REALE // metodo esteso FINE // fine della dichiarazione di classe Cilindro Attributo ereditato dalla classe Cerchio

13 Ridefinizione La classe derivata potrebbe però fornire le stesse caratteristiche della classe base differenziandosi invece per il comportamento Si definisce ereditarietà per ridefinizione (overriding) la situazione in cui uno o più metodi della classe base siano ridefiniti nella classe derivata I metodi avranno quindi la stessa segnatura (nome e lista di tipi dei parametri) ma differente corpo

14 Estensione Una classe derivata può differenziarsi dalla classe base aggiungendo nuove caratteristiche: nuovi attributi e/o nuovi metodi in questo caso si parla di estensione. L’esempio relativo alla classe Libro e LibroDiTesto è un esempio di ereditarietà per estensione: la sottoclasse aggiunge nuove caratteristiche ma non altera il comportamento delle funzionalità offerte dalla classe base.

15 Ereditare, estendere, ridefinire (1)
VeicoloAMotore AvviaMotore() MostraStato() La classe Ciclomotore: ridefinisce questi metodi La classe Ciclomotore: eredita questo metodo VeicoloA2Ruote AvviaMotore() MostraStato() Automobile La classe Ciclomotore: estende questo attributo Ciclomotore SostegnoLaterale MostraStato() InserisciSostegnoLaterale() Motocicletta La classe Ciclomotore: ridefinisce questo metodo La classe Ciclomotore: estende questo metodo

16 Ereditare, estendere, ridefinire (2)
CLASSE VeicoloAMotore INIZIO PUBBLICO Marca: STRINGA // attributi che saranno ereditati dalle sottoclassi PUBBLICO Colore: STRINGA PUBBLICO Cilindrata: INTERO PUBBLICO StatoMotore: BOOLEANO PUBBLICO AvviaMotore() // metodo che verrà ereditato dalle sottoclassi ... FINE PUBBLICO MostraStato() // metodo che verrà ereditato dalle sottoclassi SCRIVI(“Questo veicolo è un “, Marca , “ “, Colore) SE (StatoMotore = Vero) ALLORA SCRIVI(“Il motore ora è acceso”) ALTRIMENTI SCRIVI(“Il motore ora è spento”) FINESE FINE // fine del metodo MostraStato()

17 Ereditare, estendere, ridefinire (3)
CLASSE VeicoloA2Ruote EREDITA VeicoloAMotore // VeicoloAMotore è la sua superclasse INIZIO PUBBLICO AvviaMotore() // metodo ridefinito SCRIVI(“Premi contemporaneamente il freno e il pulsante di avviamento”) StatoMotore  Vero FINE PUBBLICO MostraStato() // metodo ridefinito SCRIVI(“Questa veicolo è una “, Marca , “ “, Colore) FINE // fine classe VeicoloA2Ruote

18 Ereditare, estendere, ridefinire (4)
CLASSE Ciclomotore EREDITA VeicoloA2Ruote //Ciclomotore è sottoclasse di VeicoloA2Ruote PUBBLICO SostegnoLaterale: Booleano // attributo esteso ... PUBBLICO InserisciSostegnoLaterale() // nuovo metodo INIZIO SE (StatoMotore = Falso) ALLORA SostegnoLaterale Vero ALTRIMENTI SCRIVI(“Attenzione: spegnere prima il motore”) FINESE FINE FINE // fine classe Classe Ciclomotore PUBBLICO MostraStato() // metodo ridefinito INIZIO SCRIVI(“Questa motocicletta è una “, Marca , “ “, Colore) SE (SostegnoLaterale = Vero) ALLORA SCRIVI(“Il sostegno laterale è inserito”) ALTRIMENTI SCRIVI(“Il sostegno laterale non è inserito”) FINESE SE (StatoMotore = Vero) SCRIVI(“Il motore ora è acceso”) SCRIVI(“Il motore ora è spento”) FINE // fine MostraStato() ridefinito

19 Overriding e overloading
Attenzione a non confondere il sovraccarico dei metodi (overloading) situazione in cui oltre al corpo del metodo è differente anche la sua segnatura (classico esempio è quello dei metodi costruttori) con la ridefinizione (overriding) situazione in cui la firma del metodo è identica ma è differente il corpo

20 Classi astratte Una volta che si organizzano le classi in una gerarchia di ereditarietà, si presume che le classi più “in alto” siano più astratte e generali, mentre quelle più “in basso” siano più concrete e specifiche. Spesso, quando si progetta una collezione di classi, si isola un progetto comune in una superclasse condivisa dalle singole implementazioni delle sottoclassi. Se il motivo principale dell’esistenza di una superclasse è quello di operare come centro di riferimento comune e condiviso, e si pensa di utilizzare soltanto le sue sottoclassi, tale superclasse viene detta astratta. Nel nostro esempio di gerarchie di classi, la classe VeicoliAMotore può essere un ottimo esempio di classe astratta: i suoi metodi, infatti, come ad esempio AvviaMotore(), hanno implementazioni completamente diverse nelle sottoclassi. La superclasse darà allora le linee guida sui metodi ed attributi che dovranno essere presenti nelle sottoclassi.

21 Una gerarchia con classe astratta
VeicoloAMotore VeicoloA2Ruote Automobile Ciclomotore Motocicletta

22 Classi astratte Le classi astratte non possono essere istanziate ma possono contenere tutto quanto può contenere una normale classe, compresi variabili e metodi istanza e in più possono contenere metodi astratti. Le classi astratte vengono precedute dalla parola chiave ASTRATTA. La sintassi è la seguente: ASTRATTA CLASSE <Nome classe> INIZIO <istruzione 1> <istruzione 2> <istruzione N> FINE

23 Metodi astratti I metodi astratti sono metodi con segnatura ma privi di implementazione: quest’ultima viene fornita, infatti, dalle sottoclassi della classe astratta., Vengono dichiarati con la parola chiave ASTRATTO: la sintassi generale è la seguente: ASTRATTO <NomeMetodo>([<Nome parametro>[,<Nome parametro>]):<Tipo ritorno> INIZIO <istruzione 1> <istruzione 2> …. <istruzione N> FINE

24 Attributi, metodi e classi astratte (1)
Facciamo alcune osservazioni sulla classe capostipite FiguraGeometrica della gerarchia mostrata alcune slide prima. Consideriamo i metodi Perimetro() ed Area(). Tali metodi variano a seconda della figura considerata, quindi, non possono essere implementati nella classe FiguraGeometrica. Ma, d’altra parte, tale classe deve imporre che tutte le sue sottoclassi implementino necessariamente i due metodi. La soluzione a questa situazione è quella di definire astratti i metodi Perimetro() ed Area(). I metodi astratti rappresentano un modo per riunire dei comportamenti comuni in superclassi e fornire utilizzi specifici e concreti nelle sottoclassi.

25 Attributi, metodi e classi astratte (2)
Poiché i metodi astratti sono privi di implementazione e non possono essere richiamati, essi possono esistere solo all’interno di classi astratte. Anche una classe piena di metodi concreti in cui esiste un unico metodo astratto deve, quindi, essere astratta. La classe FiguraGeometrica è un classico esempio di classe astratta. Tale classe dà solo le linee guida sui metodi ed attributi che dovranno essere implementati nelle sottoclassi. Le sottoclassi (a meno che non siano a loro volta astratte) devono necessariamente implementare (quindi ridefinire) i metodi astratti. Nel diagramma delle classi rappresentiamo una classe o un metodo astratti facendo seguire il nome della classe o del metodo dalla parola chiave astratto racchiusa tra parentesi graffe. FiguraGeometrica {ASTRATTA} Perimetro() {ASTRATTO} Area() {ASTRATTO}

26 Tipi di ereditarietà Esistono due tipi di ereditarietà:
- singola e multipla 26

27 Ereditarietà singola Si parla di ereditarietà singola quando una sottoclasse deriva da un’unica sopraclasse sopraclasse sottoclasse sottoclasse 27

28 Ereditarietà multipla
Si parla di ereditarietà multipla quando una classe deriva da due o più sopraclassi Mezzi di trasporto Animali Cavallo 28

29 Esempio nel linguaggio Java
Class veicoli { // attributi // metodi } class automobile extends veicoli Eredita attributi e metodi della classe veicoli … e ne può aggiungere di nuovi 29

30 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

31 Accedere alla superclasse
L’oggetto derivato contiene tutti i componenti (attributi e metodi) dell’oggetto da cui deriva In una gerarchia di classi può essere necessario far riferimento ad un attributo o metodo della superclasse, in questo caso si utilizza la parola chiave SUPER.

32 Super (1) VeicoloAMotore VeicoloA2Ruote VeicoloA4Ruote Ciclomotore
Processo di generalizzazione Processo di specializzazione VeicoloA2Ruote VeicoloA4Ruote Ciclomotore Scooter Motocicletta

33 Super (2) all’interno di un metodo di Motocicletta::
INIZIO /*istruzioni varie*/ SUPER.AvviaMotore() Viene richiamato il metodo AvviaMotore() di Motocicletta /*istruzioni varie*/   AvviaMotore() FINE Viene richiamato il metodo AvviaMotore() di Veicolia2Ruote Viene richiamato il metodo AvviaMotore() di Motocicletta

34 Polimorfismo Con il termine polimorfismo si intende la capacità di definire comportamenti diversi (a seconda del contesto in cui ci si trova) in risposta ai medesimi stimoli esterni. Detto in altre parole, un oggetto denota un aspetto polimorfo quando può rispondere in modo diverso a seconda del contesto in cui si trova. L’oggetto è, cioè, in grado di adattarsi al contesto in cui si trova. Possiamo classificare il polimorfismo in: polimorfismo orizzontale o polimorfismo per metodi; polimorfismo mediante overriding (“riscrittura”) polimorfismo mediante overloading (“sovraccaricamento”) rispetto al tipo (dei parametri); rispetto alla posizione (dei parametri); rispetto al numero (dei parametri). polimorfismo verticale o polimorfismo per dati o per classi;

35 Polimorfismo per metodi mediante overriding (1)
Consideriamo la gerarchia di classi: VeicoloAMotore - VeicoloA2Ruote - Motocicletta - Automobile. Da questa figura si evince che il metodo AvviaMotore() presente nella classe VeicoliA2Ruote è stato ridefinito su ogni classe della gerarchia. Questo vuol dire che si è adeguato il metodo alle particolari esigenze delle varie sottoclassi. In questi casi si dice che il metodo AvviaMotore() denota, all’interno della gerarchia di classe, un aspetto polimorfo cioè cambia forma a seconda della classe (del contesto) in cui si trova. VeicoloAMotore AvviaMotore() Automobile Motocicletta VeicoloA2Ruote

36 Polimorfismo per metodi mediante overriding (2)
Il polimorfismo per overriding (sovrascrittura) è dunque la capacità espressa dai metodi ridefiniti di assumere forme (per forme intendiamo implementazioni) diverse all’interno di una gerarchia di classi o all’interno di una stessa classe. Quando un altro oggetto richiama il metodo AvviaMotore() di un oggetto facente parte della classe Motocicletta, il metodo AvviaMotore() viene cercato prima nella sottoclasse Motocicletta. Se viene trovato (stessa segnatura della chiamata) sarà eseguito, altrimenti viene ricercato risalendo nell’albero della gerarchia di classe. Nel nostro caso è ricercato nella superclasse VeicoloA2Ruote (Fig. A3.9) e, se ancora non presente, sarà cercato nella classe VeicoloAMotore. Un altro esempio di metodo polimorfo è perimetro() il metodo che calcola il perimetro nella gerarchia delle figure geometriche.

37 Polimorfismo mediante overloading di metodi (1)
Un altro tipo di polimorfismo è quello che consente di inserire, all’interno di una classe, metodi che hanno lo stesso nome, ma differente lista di parametri (come, ad esempio, avviene in Java o in altri linguaggi). Quando il metodo viene richiamato, la scelta corretta del metodo da eseguire viene effettuata contando il numero e verificando il tipo dei parametri. Questa situazione è nota come overloading o sovraccaricamento dei metodi. Un chiaro esempio di overloading lo abbiamo visto nella prima unità parlando dei metodi costruttori. Si possono avere, infatti, più metodi costruttori necessariamente con lo stesso nome (il nome della classe) che si differenziano solo per la loro lista di parametri.

38 Polimorfismo mediante overloading di metodi (2)
Esistono tre diversi tipi di overloading: Tipale: il numero dei parametri è lo stesso ma i tipi sono diversi Ad esempio: Addiziona( A: INTERO, B: INTERO) Addiziona( A: INTERO, B: REALE) Posizionale: il numero e il tipo dei parametri sono gli stessi ma la posizione è diversa Addiziona( A: REALE, B: INTERO) Numerico: il numero dei parametri è diverso Addiziona( A: INTERO, B: INTERO, C: REALE)

39 Polimorfismo per dati Cambio di classe per un oggetto: il casting
Supponiamo di avere due oggetti di nome X e Y; X è un VeicoloA2Ruote e Y è una Motocicletta. X: VeicoloA2Ruote Y: Motocicletta X  NUOVO VeicoloA2Ruote() Y  NUOVO Motocicletta() X e Y appartengono gerarchia di classi mostrata a lato: Cosa possiamo dire delle seguenti istruzioni di assegnazione? X  Y (1) Y  X (2) Un oggetto di una classe può diventare un oggetto di un’altra classe? La prima istruzione è più immediata, perché se Y è una Motocicletta, è sicuramente anche un VeicoloA2Ruote. Non è invece così scontata la seconda: infatti se X è un VeicoloA2Ruote, potrebbe non essere una Motocicletta, ma uno scooter o un ciclomotore. VeicoloA2Ruote Motocicletta X Y

40 (<NomeNuovaClasse>)
Il casting Nei linguaggi Object Oriented è possibile il casting di classe, ovvero l’operazione che consente di forzare un oggetto di una classe a diventare un oggetto di un’altra classe, purché le classi appartengano allo stesso ramo della gerarchia. In particolare parleremo di casting implicito quando la classe di partenza è una sottoclasse della classe di arrivo (come nell’istruzione di assegnazione 1, che sarà un’istruzione legale, cioè permessa). Effettueremo un casting esplicito quando la classe di partenza è una superclasse della classe di arrivo (come nell’istruzione di assegnazione 2). Il casting esplicito viene indicato attraverso l’operatore di casting: (<NomeNuovaClasse>) dove <NomeNuovaClasse> è il nome della classe di arrivo. Nel nostro esempio, quindi, riscriveremo l’istruzione 2 nel seguente modo: Y  (Motocicletta) X

41 Binding statico e binding dinamico
Nella programmazione imperativa quando il compilatore incontra una chiamata di una funzione con i relativi parametri attuali, riesce sempre e subito a realizzare un legame tra tali parametri e la funzione che deve essere chiamata e si parla, in tal caso, di binding statico o early binding Nella programmazione ad oggetti, invece, il concetto di polimorfismo è strettamente collegato a quello di binding dinamico o associazione posticipata o ancora collegamento ritardato (late binding) Il binding dinamico riguarda l’impossibilità di stabilire, a tempo di compilazione, quale sarà il metodo da legare alla chiamata

42 Un esempio di binding dinamico
CLASSE VeicoloAMotore PUBBLICO AvviaMotore() INIZIO MostraStato() FINE PUBBLICO MostraStato() FINE /*VeicoloAMotore*/ CLASSE Scooter EREDITA VeicoloAMotore FINE /*Scooter*/ Se X=0

43 Un esempio di binding dinamico
CLASSE VeicoloAMotore PUBBLICO AvviaMotore() INIZIO MostraStato() FINE PUBBLICO MostraStato() FINE /*VeicoloAMotore*/ CLASSE Scooter EREDITA VeicoloAMotore FINE /*Scooter*/ Se X≠0

44 I metodi distruttori I metodi distruttori o conclusivi sono un po’ il contrario dei costruttori: un costruttore alloca ed inizializza l’oggetto, mentre un metodo distruttore è richiamato per svolgere le azioni finali prima di deallocare cioè liberare la sua memoria. Questa memoria può essere liberata in modo esplicito dal programmatore, utilizzando opportune primitive del linguaggio, oppure in modo implicito dal sistema. Nel nostro pseudocodice per allocare memoria ad un oggetto utilizzavamo il l’operatore NUOVO. Il metodo che libera tutta la memoria occupata, è il metodo distruttore la cui sintassi è: <Nome oggetto>.Elimina() Tale metodo potrà essere chiamato esplicitamente dal programmatore o essere richiamato automaticamente dal sistema. Quindi la chiamata: X.Elimina() avrà l’effetto di liberare lo spazio in memoria per l’oggetto (non il suo riferimento).


Scaricare ppt "Ereditarietà e polimorfismo"

Presentazioni simili


Annunci Google