Polymorphisme (Guide de programmation C#)
Par héritage, une classe peut être utilisée comme plusieurs types ; elle peut être utilisée comme son propre type, tout type de base ou tout type d'interface si elle implémente des interfaces. C'est ce qu'on appelle le polymorphisme. En C#, chaque type est polymorphe. Les types peuvent être utilisés comme leur propre type ou comme une instance Object, car tout type traite automatiquement Object comme un type de base.
Le polymorphisme est important non seulement pour les classes dérivées, mais aussi pour les classes de base. N'importe qui utilisant la classe de base pourrait, en fait, utiliser un objet de la classe dérivée qui a été castée en type de classe de base. Les concepteurs d'une classe de base peuvent anticiper les aspects de leur classe de base qui est sont susceptibles de changer pour un type dérivé. Par exemple, une classe de base pour voitures peut contenir un comportement qui est variable suivant que la voiture en question est un monospace ou une décapotable. Une classe de base peut marquer ces membres de classe comme virtuels, autorisant les classes dérivées représentant les décapotables ou les monospaces à substituer ce comportement.
Pour plus d'informations, consultez Héritage.
Vue d'ensemble du polymorphisme
Lorsqu'une classe dérivée hérite d'une classe de base, elle gagne toutes les méthodes, champs, propriétés et événements de la classe de base. Pour modifier les données et le comportement d'une classe de base, vous avez deux choix : vous pouvez substituer le membre de base par un nouveau membre dérivé, ou remplacer un membre de base virtuel.
Le remplacement d'un membre d'une classe de base par un nouveau membre dérivé nécessite le mot clé new. Si une classe de base définit une méthode, champ ou propriété, le mot clé new permet de créer une nouvelle définition de cette méthode, champ ou propriété sur une classe dérivée. Le mot clé new est placé avant le type de retour d'un membre de classe qui est remplacé. Par exemple :
public class BaseClass { public void DoWork() { } public int WorkField; public int WorkProperty { get { return 0; } } } public class DerivedClass : BaseClass { public new void DoWork() { } public new int WorkField; public new int WorkProperty { get { return 0; } } }
Lorsque le mot clé new est utilisé, les membres de la nouvelle classe sont appelés à la place des membres de la classe de base qui ont été remplacés. Ces membres de la classe de base sont appelés des membres masqués. Les membres de classe masqués peuvent encore être appelés si une instance de la classe dérivée est castée en une instance de la classe de base. Par exemple :
DerivedClass B = new DerivedClass(); B.DoWork(); // Calls the new method. BaseClass A = (BaseClass)B; A.DoWork(); // Calls the old method.
Pour qu'une instance de classe dérivée substitue complètement un membre de classe d'une classe de base, la classe de base doit déclarer ce membre comme virtuel. Cela se fait par l'ajout du mot clé virtual avant le type de retour du membre. Une classe dérivée a ensuite l'option d'utiliser le mot clé override, plutôt que new, pour remplacer l'implémentation de la classe de base par la sienne. Par exemple :
public class BaseClass { public virtual void DoWork() { } public virtual int WorkProperty { get { return 0; } } } public class DerivedClass : BaseClass { public override void DoWork() { } public override int WorkProperty { get { return 0; } } }
Les champs ne peuvent pas être virtuels. Seuls les méthodes, propriétés, événements et indexeurs peuvent être virtuels. Lorsqu'une classe dérivée substitue un membre virtuel, ce dernier est appelé même lorsqu'une instance de cette classe fait l'objet d'un accès en tant qu'instance de la classe de base. Par exemple :
DerivedClass B = new DerivedClass(); B.DoWork(); // Calls the new method. BaseClass A = (BaseClass)B; A.DoWork(); // Also calls the new method.
Les méthodes virtuelles et les propriétés vous permettent d'anticiper les extensions futures. Étant donné qu'un membre virtuel est appelé quel que soit le type utilisé par l'appelant, il donne aux classes dérivées la possibilité de modifier complètement le comportement apparent de la classe de base.
Les membres virtuels restent indéfiniment virtuels, quel que soit le nombre de classes qui ont été déclarées depuis la classe qui a déclaré le membre virtuel à l'origine. Si la classe A déclare un membre virtuel, que la classe B dérive de A, et que la classe C dérive de B, la classe C hérite du membre virtuel et a la possibilité de le remplacer, que la classe B ait déclaré une substitution pour ce membre ou non. Par exemple :
public class A { public virtual void DoWork() { } } public class B : A { public override void DoWork() { } }
Une classe dérivée peut arrêter l'héritage virtuel en déclarant une substitution comme sealed. Cela nécessite de placer le mot clé sealed avant le mot clé override dans la déclaration du membre de classe. Par exemple :
Dans l'exemple précédent, la méthode DoWork n'est plus virtuelle aux classes dérivées de C. Elle demeure virtuelle pour les instances de C, même si elles sont castées en type B ou A. Les méthodes sealed peuvent être remplacées par les classes dérivées à l'aide du mot clé new, comme le montre l'exemple suivant :
Dans ce cas, si DoWork est appelée sur D à l'aide d'une variable de type D, la nouvelle DoWork est appelée. Si une variable de type C, B, ou A est utilisée pour accéder à une instance de D, un appel à DoWork suivra les règles de l'héritage virtuel, en routant ces appels vers l'implémentation de DoWork sur la classe C.
Une classe dérivée qui a remplacé ou a substitué une méthode ou propriété peut toujours accéder à la méthode ou à la propriété de la classe de base à l'aide du mot clé base. Par exemple :
public class A { public virtual void DoWork() { } } public class B : A { public override void DoWork() { } }
public class C : B { public override void DoWork() { // Call DoWork on B to get B's behavior: base.DoWork(); // DoWork behavior specific to C goes here: // ... } }
Pour plus d'informations, consultez base.
Remarque |
|---|
|
Il est recommandé que les membres virtuels utilisent la base pour appeler l'implémentation de la classe de base de ce membre dans leur propre implémentation. Laisser le comportement de la classe de base se produire permet à la classe dérivée de se concentrer sur l'implémentation d'un comportement spécifique à la classe dérivée. Si l'implémentation de classe de base n'est pas appelée, c'est à la classe dérivée de rendre son comportement compatible avec le comportement de la classe de base. |
Dans cette section
Pour plus d'informations
Voir aussi
Référence
Héritage (Guide de programmation C#)Classes abstract et sealed et membres de classe (Guide de programmation C#)
Méthodes (Guide de programmation C#)
Propriétés (Guide de programmation C#)
Indexeurs (Guide de programmation C#)
Concepts
Guide de programmation C#Guide de programmation C#
Événements (Guide de programmation C#)
Remarque