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

bookPolymorphisme

Le terme Polymorphisme signifie « se présenter 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 à 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.

Habituellement, lors de la création d’un objet d’une classe, une variable est créée pour contenir la référence de cet objet. Le type de la variable correspond généralement à la classe de cet objet.

Par exemple :

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

Cependant, il est également possible de créer une variable de la classe de base et d’y stocker un objet d’une classe dérivée.

Par exemple :

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'attribut breed de l'objet Dog n'est pas accessible car lorsque vous stockez l'objet Dog dans une variable de type Mammal, il est implicitement converti en Mammal. Cela signifie que vous ne pouvez 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 on peut dire qu'elle est essentiellement cachée.

Vous pouvez simplement convertir example en un Dog via un transtypage explicite et l'attribut breed redeviendra disponible :

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

Cependant, pour les méthodes, il existe une fonctionnalité supplémentaire appelée surcharge de méthode (method overriding), qui ressemble quelque peu à la surchage de méthode (method overloading). Dans ce cas, il s'agit essentiellement de redéfinir une méthode d'une classe de base dans la classe dérivée.

Par exemple, vous pouvez vouloir que Mammal possède une méthode speak() telle qu'elle affiche Woof! si elle est appelée depuis un objet Dog, et Meow! si elle est appelée depuis un objet 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(); } }

Les avertissements obtenus lors de cette compilation sont dus à la superposition des noms de méthodes dans les classes parentes et enfants. Dans ce cas, il y a un chevauchement entre les méthodes speak des classes Cat et Mammal, ainsi qu'entre Dog et Mammal, ce qui explique la présence de deux avertissements.

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

Si vous souhaitez que la méthode speak se comporte comme dans son objet d'origine, il suffit de la convertir en méthode virtuelle. Une méthode virtuelle est simplement une méthode qui permet d'être redéfinie dans les classes dérivées de telle sorte que l'implémentation spécifique exécutée soit déterminée à l'exécution en fonction du type de l'objet d'origine.

Pour rendre une méthode virtuelle, il suffit d'ajouter le mot-clé virtual avant son type de retour :

index.cs

index.cs

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

Pour créer une implémentation substituée de cette méthode, utiliser le mot-clé override avant le type de retour dans l’implémentation de la nouvelle version dans la classe dérivée :

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

Assemblons maintenant les deux extraits de code et observons l'effet sur la sortie :

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

Vous constatez que dans la sortie, m2 et m3 utilisent l'implémentation de la méthode propre à Cat et Dog, car ces objets étaient à l'origine de type Cat et Dog. Ce processus d'écrasement des méthodes afin qu'elles se comportent selon leur type d'origine s'appelle polymorphisme.

Une situation où cela peut s'avérer très utile est la possibilité de stocker des objets de plusieurs types de données différents dans un seul tableau ou une seule liste.

Par exemple :

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

2. Quelle est la manière correcte de rendre une méthode substituable ?

question mark

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

Select the correct answer

question mark

Quelle est la manière correcte de rendre une méthode substituable ?

Select the correct answer

Tout était clair ?

Comment pouvons-nous l'améliorer ?

Merci pour vos commentaires !

Section 5. Chapitre 4

Demandez à l'IA

expand

Demandez à l'IA

ChatGPT

Posez n'importe quelle question ou essayez l'une des questions suggérées pour commencer notre discussion

Awesome!

Completion rate improved to 2.04

bookPolymorphisme

Glissez pour afficher le menu

Le terme Polymorphisme signifie « se présenter 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 à 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.

Habituellement, lors de la création d’un objet d’une classe, une variable est créée pour contenir la référence de cet objet. Le type de la variable correspond généralement à la classe de cet objet.

Par exemple :

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

Cependant, il est également possible de créer une variable de la classe de base et d’y stocker un objet d’une classe dérivée.

Par exemple :

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'attribut breed de l'objet Dog n'est pas accessible car lorsque vous stockez l'objet Dog dans une variable de type Mammal, il est implicitement converti en Mammal. Cela signifie que vous ne pouvez 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 on peut dire qu'elle est essentiellement cachée.

Vous pouvez simplement convertir example en un Dog via un transtypage explicite et l'attribut breed redeviendra disponible :

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

Cependant, pour les méthodes, il existe une fonctionnalité supplémentaire appelée surcharge de méthode (method overriding), qui ressemble quelque peu à la surchage de méthode (method overloading). Dans ce cas, il s'agit essentiellement de redéfinir une méthode d'une classe de base dans la classe dérivée.

Par exemple, vous pouvez vouloir que Mammal possède une méthode speak() telle qu'elle affiche Woof! si elle est appelée depuis un objet Dog, et Meow! si elle est appelée depuis un objet 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(); } }

Les avertissements obtenus lors de cette compilation sont dus à la superposition des noms de méthodes dans les classes parentes et enfants. Dans ce cas, il y a un chevauchement entre les méthodes speak des classes Cat et Mammal, ainsi qu'entre Dog et Mammal, ce qui explique la présence de deux avertissements.

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

Si vous souhaitez que la méthode speak se comporte comme dans son objet d'origine, il suffit de la convertir en méthode virtuelle. Une méthode virtuelle est simplement une méthode qui permet d'être redéfinie dans les classes dérivées de telle sorte que l'implémentation spécifique exécutée soit déterminée à l'exécution en fonction du type de l'objet d'origine.

Pour rendre une méthode virtuelle, il suffit d'ajouter le mot-clé virtual avant son type de retour :

index.cs

index.cs

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

Pour créer une implémentation substituée de cette méthode, utiliser le mot-clé override avant le type de retour dans l’implémentation de la nouvelle version dans la classe dérivée :

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

Assemblons maintenant les deux extraits de code et observons l'effet sur la sortie :

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

Vous constatez que dans la sortie, m2 et m3 utilisent l'implémentation de la méthode propre à Cat et Dog, car ces objets étaient à l'origine de type Cat et Dog. Ce processus d'écrasement des méthodes afin qu'elles se comportent selon leur type d'origine s'appelle polymorphisme.

Une situation où cela peut s'avérer très utile est la possibilité de stocker des objets de plusieurs types de données différents dans un seul tableau ou une seule liste.

Par exemple :

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

2. Quelle est la manière correcte de rendre une méthode substituable ?

question mark

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

Select the correct answer

question mark

Quelle est la manière correcte de rendre une méthode substituable ?

Select the correct answer

Tout était clair ?

Comment pouvons-nous l'améliorer ?

Merci pour vos commentaires !

Section 5. Chapitre 4
some-alt