Polymorphisme
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
123Dog 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
1234567891011121314151617181920212223242526272829303132using 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
12345678910111213141516171819202122232425262728293031323334353637383940using 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
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647using 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
1234567class 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
123456789101112131415class 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
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647using 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
123456789List<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 ?
Merci pour vos commentaires !
Demandez à l'IA
Demandez à l'IA
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
Polymorphisme
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
123Dog 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
1234567891011121314151617181920212223242526272829303132using 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
12345678910111213141516171819202122232425262728293031323334353637383940using 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
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647using 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
1234567class 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
123456789101112131415class 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
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647using 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
123456789List<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 ?
Merci pour vos commentaires !