Andrea Zoccheddu Oggetti in C# Lezione 5 Polimorfismo I.

Post on 02-May-2015

258 views 7 download

Transcript of Andrea Zoccheddu Oggetti in C# Lezione 5 Polimorfismo I.

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