Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Impara Polimorfismo | Principi OOP
C# Oltre le Basi

bookPolimorfismo

Il termine Polimorfismo significa "presentarsi in diverse forme". Nel contesto della programmazione orientata agli oggetti, il polimorfismo si riferisce alla capacità di una classe di fornire un'interfaccia comune per le sue classi derivate, consentendo a ciascuna classe derivata di implementare comportamenti specifici per i metodi ereditati.

Normalmente, quando si crea un oggetto di una classe, si crea una variabile per contenere il riferimento a quell'oggetto. Il tipo della variabile è solitamente la classe di quell'oggetto.

Ad esempio:

index.cs

index.cs

copy
123
Dog myVar = new Dog(); // or even in case of implicit declaration, 'myVar' will be of type 'Dog' var myVar = new Dog();

Tuttavia, è anche possibile creare una variabile di una classe base e memorizzare in essa un oggetto di una classe derivata.

Ad esempio:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132
using System; class Mammal { public int age; public Mammal(int age) { this.age = age; } } class Dog : Mammal { public string breed; public Dog(int age, string breed) : base(age) { this.breed = breed; } } class ConsoleApp { static void Main() { Mammal example = new Dog(10, "Labrador"); Console.WriteLine(example.age); Console.WriteLine(example.breed); // Error because it's not accessible (read explanation below) } }

L'attributo breed dell'oggetto Dog non è accessibile perché, quando si memorizza l'oggetto Dog in una variabile di tipo Mammal, esso viene convertito implicitamente in Mammal. Questo significa che si possono accedere solo agli attributi e ai metodi presenti nella classe Mammal. Tuttavia, il valore memorizzato nella classe breed non viene perso, ma semplicemente reso inaccessibile e si può dire che sia nascosto.

È possibile convertire example in un oggetto Dog tramite un cast esplicito di tipo e l'attributo breed tornerà disponibile:

index.cs

index.cs

copy
12345678910111213141516171819202122232425262728293031323334353637383940
using System; class Mammal { public int age; public Mammal(int age) { this.age = age; } public void speak() { // Empty for now } } class Dog : Mammal { public string breed; public Dog(int age, string breed) : base(age) { this.breed = breed; } } class ConsoleApp { static void Main() { Mammal example = new Dog(10, "Labrador"); Console.WriteLine(example.age); Dog casted = (Dog)example; Console.WriteLine(casted.breed); } }

Tuttavia, per i metodi esiste una funzionalità aggiuntiva chiamata override del metodo, che è in qualche modo simile al sovraccarico del metodo. In questo caso, si ridefinisce essenzialmente un metodo di una classe base nella classe derivata.

Ad esempio, si può voler che Mammal abbia un metodo speak() tale che produca Woof! se viene chiamato da un oggetto Dog, e Meow! se viene chiamato da un oggetto Cat:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
using System; class Mammal { public void speak() { Console.WriteLine("Mammal Speaks"); } } class Dog : Mammal { public void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public void speak() { Console.WriteLine("Meow!"); } } class ConsoleApp { static void Main() { // The following execute the overriden version of the methods Dog d1 = new Dog(); d1.speak(); Cat c1 = new Cat(); c1.speak(); Mammal m1 = new Mammal(); Mammal m2 = new Cat(); Mammal m3 = new Dog(); // All of these execute the 'Mammal' version of the method m1.speak(); m2.speak(); m3.speak(); } }

Gli avvisi che si ricevono durante questa compilazione sono dovuti alla sovrapposizione dei nomi dei metodi nelle classi padre e figlio. In questo caso, c'è una sovrapposizione tra i metodi speak delle classi Cat e Mammal, e anche tra Dog e Mammal, motivo per cui si ricevono due avvisi.

Tuttavia, si noti alla fine come m1, m2 e m3 eseguano il metodo definito nella classe Mammal, poiché sono stati convertiti in oggetti di tipo Mammal.

Se si desidera che il metodo speak si comporti come nel suo oggetto originale, è sufficiente convertirlo in un metodo virtuale. Un metodo virtuale è semplicemente un metodo che consente di essere sovrascritto dalle classi derivate in modo tale che l'implementazione specifica eseguita venga determinata a runtime in base al tipo dell'oggetto originale.

Per rendere un metodo virtuale, basta aggiungere la parola chiave virtual prima del suo tipo di ritorno:

index.cs

index.cs

copy
1234567
class Mammal { public virtual void speak() { Console.WriteLine("Mammal Speaks"); } }

Per creare un'implementazione sovrascritta di questo metodo, utilizzare la parola chiave override prima del tipo di ritorno nell'implementazione della nuova versione nella classe derivata:

index.cs

index.cs

copy
123456789101112131415
class Dog : Mammal { public override void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public override void speak() { Console.WriteLine("Meow!"); } }

Mettiamo ora insieme i due frammenti di codice e vediamo come questo influisce sull'output:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
using System; class Mammal { public virtual void speak() { Console.WriteLine("Mammal Speaks"); } } class Dog : Mammal { public override void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public override void speak() { Console.WriteLine("Meow!"); } } class ConsoleApp { static void Main() { Mammal m1 = new Mammal(); Mammal m2 = new Cat(); Mammal m3 = new Dog(); m1.speak(); // Since it stores a Mammal() object, it executes the Mammal's implementation m2.speak(); // Output: Meow! m3.speak(); // Output: Woof! // The following behave the same as they did in the previous example: Dog d1 = new Dog(); d1.speak(); Cat c1 = new Cat(); c1.speak(); } }

Si nota che nell'output, m2 e m3 utilizzano l'implementazione del metodo di Cat e Dog perché quegli oggetti erano originariamente Cat e Dog. Questo intero processo di sovrascrittura dei metodi in modo che si comportino in base al loro tipo originale è chiamato polimorfismo.

Una situazione in cui questo può essere molto utile è la possibilità di memorizzare oggetti di diversi tipi di dati in un unico array o elenco.

Ad esempio:

index.cs

index.cs

copy
123456789
List<Shape> shapes = new List<Shape>(); shapes.Add(new Rectangle(25, 50)); shapes.Add(new Square(50)); shapes.Add(new Circle(10)); shapes[0].getArea(); // Output: 1250.0f shapes[1].getArea(); // Output: 2500.0f shapes[2].getArea(); // Output: 314.15f

1. Quali sono le due parole chiave utilizzate nell'override dei metodi?

2. Qual è il modo corretto per rendere un metodo sovrascrivibile?

question mark

Quali sono le due parole chiave utilizzate nell'override dei metodi?

Select the correct answer

question mark

Qual è il modo corretto per rendere un metodo sovrascrivibile?

Select the correct answer

Tutto è chiaro?

Come possiamo migliorarlo?

Grazie per i tuoi commenti!

Sezione 5. Capitolo 4

Chieda ad AI

expand

Chieda ad AI

ChatGPT

Chieda pure quello che desidera o provi una delle domande suggerite per iniziare la nostra conversazione

Awesome!

Completion rate improved to 2.04

bookPolimorfismo

Scorri per mostrare il menu

Il termine Polimorfismo significa "presentarsi in diverse forme". Nel contesto della programmazione orientata agli oggetti, il polimorfismo si riferisce alla capacità di una classe di fornire un'interfaccia comune per le sue classi derivate, consentendo a ciascuna classe derivata di implementare comportamenti specifici per i metodi ereditati.

Normalmente, quando si crea un oggetto di una classe, si crea una variabile per contenere il riferimento a quell'oggetto. Il tipo della variabile è solitamente la classe di quell'oggetto.

Ad esempio:

index.cs

index.cs

copy
123
Dog myVar = new Dog(); // or even in case of implicit declaration, 'myVar' will be of type 'Dog' var myVar = new Dog();

Tuttavia, è anche possibile creare una variabile di una classe base e memorizzare in essa un oggetto di una classe derivata.

Ad esempio:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132
using System; class Mammal { public int age; public Mammal(int age) { this.age = age; } } class Dog : Mammal { public string breed; public Dog(int age, string breed) : base(age) { this.breed = breed; } } class ConsoleApp { static void Main() { Mammal example = new Dog(10, "Labrador"); Console.WriteLine(example.age); Console.WriteLine(example.breed); // Error because it's not accessible (read explanation below) } }

L'attributo breed dell'oggetto Dog non è accessibile perché, quando si memorizza l'oggetto Dog in una variabile di tipo Mammal, esso viene convertito implicitamente in Mammal. Questo significa che si possono accedere solo agli attributi e ai metodi presenti nella classe Mammal. Tuttavia, il valore memorizzato nella classe breed non viene perso, ma semplicemente reso inaccessibile e si può dire che sia nascosto.

È possibile convertire example in un oggetto Dog tramite un cast esplicito di tipo e l'attributo breed tornerà disponibile:

index.cs

index.cs

copy
12345678910111213141516171819202122232425262728293031323334353637383940
using System; class Mammal { public int age; public Mammal(int age) { this.age = age; } public void speak() { // Empty for now } } class Dog : Mammal { public string breed; public Dog(int age, string breed) : base(age) { this.breed = breed; } } class ConsoleApp { static void Main() { Mammal example = new Dog(10, "Labrador"); Console.WriteLine(example.age); Dog casted = (Dog)example; Console.WriteLine(casted.breed); } }

Tuttavia, per i metodi esiste una funzionalità aggiuntiva chiamata override del metodo, che è in qualche modo simile al sovraccarico del metodo. In questo caso, si ridefinisce essenzialmente un metodo di una classe base nella classe derivata.

Ad esempio, si può voler che Mammal abbia un metodo speak() tale che produca Woof! se viene chiamato da un oggetto Dog, e Meow! se viene chiamato da un oggetto Cat:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
using System; class Mammal { public void speak() { Console.WriteLine("Mammal Speaks"); } } class Dog : Mammal { public void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public void speak() { Console.WriteLine("Meow!"); } } class ConsoleApp { static void Main() { // The following execute the overriden version of the methods Dog d1 = new Dog(); d1.speak(); Cat c1 = new Cat(); c1.speak(); Mammal m1 = new Mammal(); Mammal m2 = new Cat(); Mammal m3 = new Dog(); // All of these execute the 'Mammal' version of the method m1.speak(); m2.speak(); m3.speak(); } }

Gli avvisi che si ricevono durante questa compilazione sono dovuti alla sovrapposizione dei nomi dei metodi nelle classi padre e figlio. In questo caso, c'è una sovrapposizione tra i metodi speak delle classi Cat e Mammal, e anche tra Dog e Mammal, motivo per cui si ricevono due avvisi.

Tuttavia, si noti alla fine come m1, m2 e m3 eseguano il metodo definito nella classe Mammal, poiché sono stati convertiti in oggetti di tipo Mammal.

Se si desidera che il metodo speak si comporti come nel suo oggetto originale, è sufficiente convertirlo in un metodo virtuale. Un metodo virtuale è semplicemente un metodo che consente di essere sovrascritto dalle classi derivate in modo tale che l'implementazione specifica eseguita venga determinata a runtime in base al tipo dell'oggetto originale.

Per rendere un metodo virtuale, basta aggiungere la parola chiave virtual prima del suo tipo di ritorno:

index.cs

index.cs

copy
1234567
class Mammal { public virtual void speak() { Console.WriteLine("Mammal Speaks"); } }

Per creare un'implementazione sovrascritta di questo metodo, utilizzare la parola chiave override prima del tipo di ritorno nell'implementazione della nuova versione nella classe derivata:

index.cs

index.cs

copy
123456789101112131415
class Dog : Mammal { public override void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public override void speak() { Console.WriteLine("Meow!"); } }

Mettiamo ora insieme i due frammenti di codice e vediamo come questo influisce sull'output:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
using System; class Mammal { public virtual void speak() { Console.WriteLine("Mammal Speaks"); } } class Dog : Mammal { public override void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public override void speak() { Console.WriteLine("Meow!"); } } class ConsoleApp { static void Main() { Mammal m1 = new Mammal(); Mammal m2 = new Cat(); Mammal m3 = new Dog(); m1.speak(); // Since it stores a Mammal() object, it executes the Mammal's implementation m2.speak(); // Output: Meow! m3.speak(); // Output: Woof! // The following behave the same as they did in the previous example: Dog d1 = new Dog(); d1.speak(); Cat c1 = new Cat(); c1.speak(); } }

Si nota che nell'output, m2 e m3 utilizzano l'implementazione del metodo di Cat e Dog perché quegli oggetti erano originariamente Cat e Dog. Questo intero processo di sovrascrittura dei metodi in modo che si comportino in base al loro tipo originale è chiamato polimorfismo.

Una situazione in cui questo può essere molto utile è la possibilità di memorizzare oggetti di diversi tipi di dati in un unico array o elenco.

Ad esempio:

index.cs

index.cs

copy
123456789
List<Shape> shapes = new List<Shape>(); shapes.Add(new Rectangle(25, 50)); shapes.Add(new Square(50)); shapes.Add(new Circle(10)); shapes[0].getArea(); // Output: 1250.0f shapes[1].getArea(); // Output: 2500.0f shapes[2].getArea(); // Output: 314.15f

1. Quali sono le due parole chiave utilizzate nell'override dei metodi?

2. Qual è il modo corretto per rendere un metodo sovrascrivibile?

question mark

Quali sono le due parole chiave utilizzate nell'override dei metodi?

Select the correct answer

question mark

Qual è il modo corretto per rendere un metodo sovrascrivibile?

Select the correct answer

Tutto è chiaro?

Come possiamo migliorarlo?

Grazie per i tuoi commenti!

Sezione 5. Capitolo 4
some-alt