Upload
amerigo-palumbo
View
262
Download
7
Embed Size (px)
Citation preview
Andrea Zoccheddu
Oggetti in C#Oggetti in C#
Lezione 5Lezione 5
PolimorfismoPolimorfismoII
Facciamo chiarezza
Abbiamo visto che è possibile ridefinire i metodi di una classe derivata
Ma in realtà esistono due differenti modi di re-dichiarazione:
• 1. OVERLOADING, sovrapposizione
• 2. OVERRIDING, scavalcamento
OVERLOADING
È il modo più semplice di ridefinire un metodoLa classe discendente semplicemente lo dichiara e definisce di nuovo
class Felino{ public void Verso() { Console.WriteLine("MEOW"); }}//Felino
class Gatto : Felino{ public void Verso() { Console.WriteLine("MIAO"); }}//Gatto
OVERLOADING
È il modo più semplice di ridefinire un metodo
Il metodo è legato staticamenteIl f1 chiama il verso del FelinoIl g1 chiama il verso del Gatto
Felino f1 = new Felino(); f1.Verso();
Gatto g1 = new Gatto();g1.Verso();
MEOW MIAO
OVERLOADING
Nella ridefinizione si può invocare il metodo del padre
Il metodo può sfruttare quanto predisposto dal metodo paterno
class Felino{ public void Verso() { Console.WriteLine("MEOW"); }}//Felino
class Gatto : Felino{ public void Verso() { base.Verso(); Console.WriteLine("MIAO"); }}//Gatto
OVERLOADING
È il modo più semplice di ridefinire un metodo
Il metodo è legato staticamenteIl f1 chiama il verso del FelinoIl g1 chiama il verso del Gatto
Felino f1 = new Felino(); f1.Verso();
Gatto g1 = new Gatto();g1.Verso();
MEOWMEOWMIAO
Andrea Zoccheddu
un casoun caso
particolareparticolare
Un caso particolare
Ma si osservi questa situazione:class Felino{
public void Fusa (){Console.WriteLine("Grrr");}
public void Contento(){this.Fusa();Console.WriteLine("Struscia");}
}//Felino
class Gatto : Felino{
public void Fusa (){Console.WriteLine("Prrr");}
public void Contento(){this.Fusa();Console.WriteLine("Struscia");}
}//Gatto
i metodi Contento sono molto simili
Un caso particolareQuando si invocano i metodi essi si comportano bene:
Però quei metodi «Contento» sono proprio identici… è possibile evitare di ripetere il secondo?In fondo il metodo è ereditato dal padre ...
Felino f1 = new Felino(); f1.Contento();
Gatto g1 = new Gatto();g1. Contento();
GRRRStruscia
PRRRStruscia
Un caso particolare
Le definizioni diventerebbero:class Felino{
public void Fusa (){Console.WriteLine("Grrr");}
public void Contento(){this.Fusa();Console.WriteLine("Struscia");}
}//Felino
class Gatto : Felino{
public void Fusa (){Console.WriteLine("Prrr");}
}//Gatto
il metodo Contento è ereditato da Gatto
Un caso particolare
Quando si invocano i metodi però:
Il metodo Contento del gatto usa il metodo Fusa del Felino invece del suo, ed il motivo è il legame statico
Felino f1 = new Felino(); f1.Contento();
Gatto g1 = new Gatto();g1. Contento();
GRRRStruscia
GRRRStruscia
Un caso particolare• Il problema lo causa il metodo
Contento del Felino• Quando viene compilato il
riferimento al metodo Fusa è statico e quindi impone un collegamento fisso
• Anche se è un Gatto che invoca il metodo Contento ormai il metodo è legato al metodo Fusa del Felino
Un caso particolare
• Invece vorremmo che il collegamento fosse «al volo» ovvero dinamico, a tempo di esecuzione del programma
• Così magari la macchina si accorge che si tratta di un Gatto e non di un Felino generico
Andrea Zoccheddu
polimorfismopolimorfismo
OVERRIDINGOVERRIDING
I METODI VIRTUALII METODI VIRTUALI
OVERRIDINGOVERRIDING
La situazione si può risolvere cosìclass Felino{
public virtual void Fusa (){Console.WriteLine("Grrr");}
public void Contento(){Fusa();Console.WriteLine("Struscia");}
}//Felino
class Gatto : Felino{
public override void Fusa (){Console.WriteLine("Prrr");}
}//Gatto
il metodo Contento è ereditato
Un caso particolare
Quando si invocano i metodi essi si comportano bene:
Cosa accade?Il collegamento al metodo Fusa è ritardato: si aspetta l’esecuzione della invocazione per decidere quale metodo invocare
Felino f1 = new Felino(); f1.Contento();
Gatto g1 = new Gatto();g1. Contento();
GRRRStruscia
PRRRStruscia
polimorfismo• Il polimorfismo è il concetto che
una istanza può invocare un nome di metodo che si aggancia dinamicamente al metodo corretto «al volo»
• Il polimorfismo è un paradigma di programmazione, ovvero un modello ed una tecnica di realizzazione dei programmi
• Rappresenta un modello elevato di efficienza e flessibilità
virtual
• virtual è una parola riservata• Un metodo virtual è dichiarato
come un metodo con collegamento ritardato
• Il metodo verrà cercato a partire dal tipo di istanza legata alla variabile effettiva che la invoca
• Il metodo può essere ridefinito con override
virtual
• L’ordine in cui compaiono le parole public e virtual non è importante.
• Una funzione virtuale non può essere privata, o si ha un errore di compilazione.
• Infatti una funzione privata non può essere visibile e accessibile dalle classe derivate
override• override è una parola riservata• Un metodo override indica come
eseguire il metodo nel caso di una istanza specifica
• Un metodo virtuale deve essere ridefinito con override per ottenere un collegamento dinamico
• Se uso di nuovo virtual invece sto scavalcando il metodo
override
• Una funzione con override deve fare riferimento ad una antenata virtuale o si ha un errore
• Il prototipo della funzione ridefinita deve coincidere perfettamente con quello della funzione base (public, tipo, parametri) o si ha un errore