Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Apprendre Polymorphisme | Principes de la POO
C# au-delà des Bases
course content

Contenu du cours

C# au-delà des Bases

C# au-delà des Bases

1. Structures Supplémentaires et Gestion des Fichiers
2. Structures et Énumérateurs
3. Introduction à la Programmation Orientée Objet (POO)
4. Essentiels de la POO
5. Principes de la POO

book
Polymorphisme

Le terme Polymorphisme signifie "se produire sous plusieurs formes différentes". Dans le contexte de la programmation orientée objet, le polymorphisme fait référence à la capacité d'une classe à fournir une interface commune pour ses classes dérivées tout en permettant à chaque classe dérivée d'implémenter des comportements spécifiques pour les méthodes héritées.

Normalement, lorsque nous créons un objet d'une classe, nous créons une variable pour contenir la référence de cet objet. Et le type de la variable est généralement la classe de cet objet.

Par exemple :

cs

index

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

Cependant, nous pouvons également créer une variable d'une classe de base et y stocker un objet d'une classe dérivée.

Par exemple :

cs

index

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'attribut breed de l'objet Dog n'est pas accessible car lorsque nous stockons l'objet Dog dans une variable Mammal, il est implicitement converti en Mammal. Cela signifie que nous ne pouvons accéder qu'aux attributs et méthodes présents dans la classe Mammal. Cela ne signifie pas que la valeur stockée dans la classe breed est perdue, elle est simplement inaccessible et nous pouvons dire qu'elle est essentiellement cachée.

Nous pouvons simplement convertir example en Dog par un transtypage explicite et l'attribut breed redeviendra disponible :

cs

index

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); } }

Cependant, pour les méthodes, il existe une fonctionnalité supplémentaire appelée surcharge de méthode, qui est quelque peu similaire à la surcharge de méthode, mais nous redéfinissons essentiellement une méthode d'une classe de base dans la classe dérivée.

Par exemple, nous voudrions que Mammal ait une méthode speak() de sorte qu'elle produise Woof! si elle est appelée à partir d'un objet Dog, et Meow! si elle est appelée à partir d'un objet Cat :

cs

index

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(); } }

Les avertissements que nous recevons lors de cette compilation sont dus à des noms de méthodes qui se chevauchent dans les classes parent et enfant. Dans ce cas, il y a un chevauchement entre les méthodes speak des classes Cat et Mammal, et aussi entre les classes Dog et Mammal, c'est pourquoi nous recevons deux avertissements.

Cependant, remarquez à la fin comment m1, m2 et m3 exécutent la méthode définie dans la classe Mammal, c'est parce qu'ils sont convertis en objets Mammal.

Si nous voulons que la méthode speak se comporte comme elle le fait dans son objet d'origine, nous pouvons simplement la convertir en une méthode virtuelle. Une méthode virtuelle est simplement une méthode qui nous permet de la remplacer à partir de classes dérivées de telle manière que l'implémentation spécifique exécutée est déterminée au moment de l'exécution en fonction du type de l'objet d'origine.

Pour rendre une méthode virtuelle, nous ajoutons simplement le mot-clé virtual avant son type de retour :

cs

index

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

Pour faire une implémentation remplacée de cette méthode, nous utilisons le mot-clé override avant le type de retour dans l'implémentation de cette nouvelle implémentation dans la classe dérivée :

cs

index

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

Mettons maintenant ensemble les deux extraits et voyons comment cela affecte la sortie :

cs

index

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(); } }

Vous voyez que dans la sortie, m2 et m3 utilisent l'implémentation de la méthode de Cat et Dog parce que ces objets étaient à l'origine Cat et Dog. Ce processus entier de redéfinition des méthodes de sorte qu'elles se comportent en fonction de leur type d'origine est appelé polymorphisme.

Une situation où cela peut être très utile est de pouvoir stocker des objets de plusieurs types de données différents dans un seul tableau ou une seule liste.

Par exemple :

cs

index

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. Quels sont les deux mots-clés utilisés dans la redéfinition de méthode ?

2. Quelle est la bonne façon de rendre une méthode substituable ?

Quels sont les deux mots-clés utilisés dans la redéfinition de méthode ?

Quels sont les deux mots-clés utilisés dans la redéfinition de méthode ?

Sélectionnez la réponse correcte

Quelle est la bonne façon de rendre une méthode substituable ?

Quelle est la bonne façon de rendre une méthode substituable ?

Sélectionnez la réponse correcte

Tout était clair ?

Comment pouvons-nous l'améliorer ?

Merci pour vos commentaires !

Section 5. Chapitre 4
We're sorry to hear that something went wrong. What happened?
some-alt