CodeGym /Cours /C# SELF /Redéfinition de méthodes (Method Overriding) en C#

Redéfinition de méthodes (Method Overriding) en C#

C# SELF
Niveau 21 , Leçon 2
Disponible

1. Introduction

Si le mot redéfinition te fait un peu transpirer, t’inquiète — c’est pas si terrible, c’est même super pratique ! Redéfinir une méthode, c’est la possibilité de remplacer le comportement d’une méthode de la classe de base par le tien dans une classe dérivée. Grâce à ça, ton code devient flexible, évolutif et prêt pour la vraie vie, où chaque animal n’a pas envie d’être juste "un certain bruit".

Pour autoriser la redéfinition d’une méthode, la classe de base la marque avec le mot-clé virtual. La classe dérivée, pour remplacer l’implémentation, utilise le mot-clé override.

Exemple


public class Animal
{
    public string Name { get; set; }
    public virtual void MakeSound()
    {
        Console.WriteLine("Un son universel d’animal...");
    }
}
        

Et maintenant dans la classe du chien :


public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Ouaf-ouaf !");
    }
}
        
  • Dans la classe de base — virtual.
  • Dans la classe dérivée — override.
  • La signature de la méthode (nom, type de retour, paramètres) doit être identique.

Schéma visuel

Dog hérite de Animal et peut redéfinir MakeSound()

2. Démonstration du fonctionnement

Voyons comment la redéfinition marche en vrai. On crée des animaux et on teste le son :

Animal pet1 = new Animal { Name = "Animal sans nom" };
Dog pet2 = new Dog { Name = "Barbos" };

pet1.MakeSound(); // Affichera : Un son universel d’animal...
pet2.MakeSound(); // Affichera : Ouaf-ouaf !

Maintenant, on complique un peu :
Et si on stocke un chien dans une variable de type Animal ?

Animal pet3 = new Dog { Name = "Sharik" };
pet3.MakeSound(); // ???

À ton avis, qu’est-ce qui va se passer ?
Réponse : Ça affichera "Ouaf-ouaf !"
Parce que même si la variable est de type Animal, elle "pointe" sur un chien, donc c’est la version redéfinie de la méthode qui sera appelée !
Voilà la magie du binding dynamique (ou tardif).

3. Utilisation du mot-clé base lors de la redéfinition

Parfois, on n’a pas envie de remplacer complètement l’implémentation d’une méthode, mais plutôt de l’étendre — genre ajouter un truc à soi, puis exécuter aussi l’ancien comportement. Pour ça, on utilise le mot-clé base. Il permet d’appeler la version de la méthode de la classe de base.


public class Cat : Animal
{
    public override void MakeSound()
    {
        base.MakeSound(); // appel de l’implémentation de base
        Console.WriteLine("Miaou !");
    }
}
        

Quand tu appelles cette méthode, d’abord ça écrit "Un son universel d’animal...", puis "Miaou !"

4. Comment le choix de la méthode fonctionne lors de la redéfinition

Pour bien piger ce qui se passe "sous le capot", imagine ce genre de tableau (dispatch virtuel) :

Type de variable Type d’objet Quelle méthode sera appelée
Animal Animal Animal.MakeSound
Animal Dog Dog.MakeSound
Animal Labrador Labrador.MakeSound
Dog Labrador Labrador.MakeSound
Dog Dog Dog.MakeSound

La règle principale :
Le type de la variable compte seulement pour le compilateur, mais à l’exécution c’est le type réel de l’objet (celui qu’on a créé avec new) qui décide.
Ce mécanisme s’appelle liaison dynamique (ou tardive) — c’est la base du polymorphisme (on en reparle dans la prochaine leçon !).

Pourquoi redéfinir des méthodes

  • Dans les frameworks GUI : tu as une classe de base pour une fenêtre, et tu redéfinis les méthodes pour dessiner des éléments spécifiques.
  • Dans les moteurs de jeu : classe de base Enemy, et les classes héritées font des comportements différents.
  • Dans les tests unitaires : tu peux créer des "bouchons" (stubs, mocks) pour les méthodes.

Les frameworks modernes .NET utilisent à fond ce mécanisme pour les événements, le code template, l’héritage de configs et même la sérialisation d’objets (genre via des propriétés virtuelles).

5. Le mot-clé new pour masquer des méthodes

On a déjà vu que pour redéfinir des méthodes, il faut le duo virtual/override. Mais en C#, il y a aussi un autre modificateur lié aux méthodes dans une hiérarchie d’héritage — c’est new.

À quoi sert new ?

new s’utilise si, dans une classe dérivée, tu déclares une méthode avec la même signature que dans la classe de base, MAIS tu ne veux pas redéfinir une méthode virtuelle, tu veux juste masquer (cacher) la méthode de base.

  • Ce n’est pas une redéfinition, c’est un masquage.
  • Cette méthode est appelée selon le type de la variable, pas selon le type réel de l’objet (pas de polymorphisme dynamique !).
  • Le compilateur te prévient si tu "masques" une méthode sans le mot-clé new.

Exemple : différence entre override et new


public class Animal
{
    public virtual  void MakeSound()
    {
        Console.WriteLine("L’animal fait un certain bruit...");
    }
}

public class Dog : Animal
{
    // On masque la méthode de la classe de base (PAS une redéfinition)
    public new void MakeSound()
    {
        Console.WriteLine("Ceci n’est pas un override ! Juste la méthode du chien.");
    }
}
        

Regardons le comportement :

Animal a = new Dog();
Dog d = new Dog();

a.MakeSound(); // "L’animal fait un certain bruit..."
d.MakeSound(); // "Ceci n’est pas un override ! Juste la méthode du chien."
  • Si la variable est de type Dog — c’est la méthode de Dog qui est appelée.
  • Si la variable est de type Animal, même si elle contient un Dog — c’est la méthode Animal qui est appelée !

6. Feedback et particularités d’implémentation

Quand on débute en prog, on se plante souvent en pensant qu’une méthode est "redéfinie", mais elle marche comme avant. La raison est simple : dans la classe de base, il n’y a pas virtual, ou dans la dérivée la méthode est déclarée avec new au lieu de override. Le deuxième cas est particulièrement traître — si tu appelles la méthode via une variable du type de base, c’est la version de base qui sera appelée, pas la redéfinie. Donc fais toujours gaffe à bien utiliser les bons mots-clés.

En plus des erreurs de syntaxe, parfois les débutants essaient de changer le type de retour lors de la redéfinition. Par exemple, faire une fonction de base qui retourne object, et dans la dérivée — string. Ça, c’est pas possible : la signature doit être strictement identique.

Tableau comparatif : override vs new

Particularité override new
Mécanisme Redéfinit une méthode virtuelle Masque la méthode de la classe de base
Liaison tardive Oui — fonctionne via le polymorphisme dynamique Non — fonctionne selon le type de la variable
Exige que la base soit... virtual, abstract ou déjà override Non
Recommandé d’utiliser Oui, presque toujours Seulement dans des cas exceptionnels

7. Fonctionnement des méthodes redéfinies avec les hiérarchies

Toute cette histoire de redéfinition devient vraiment fun quand on a de longues chaînes d’héritage :


public class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("L’animal fait quelque chose...");
    }
}

public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Ouaf-ouaf !");
    }
}

public class Labrador : Dog
{
    public override void MakeSound()
    {
        Console.WriteLine("Je suis un labrador : waou-waou !");
    }
}
        

Que se passe-t-il si on écrit :

Animal pet = new Labrador();
pet.MakeSound(); //   => "Je suis un labrador : waou-waou !"

C# choisira toujours l’implémentation la plus "profonde" de la méthode virtuelle qui existe sur l’objet.

8. Erreurs typiques lors de la redéfinition de méthodes

Le monde n’est pas parfait, et les étudiants (et même les devs expérimentés !) font parfois des erreurs. Apprenons tout de suite à éviter les pièges les plus fréquents :

1. Oubli de virtual dans la classe de base


public class Animal
{
    public void MakeSound() { ... } // Pas de 'virtual'
}

public class Dog : Animal
{
    // Erreur de compilation ! Impossible de redéfinir.
    public override void MakeSound()
    {
        Console.WriteLine("Ouaf !");
    }
}
        

C# dira direct : 'Dog.MakeSound()': no suitable method found to override

2. Signatures différentes

Vérifie bien que le nom de la méthode, le type de retour et les paramètres sont identiques :


public class Animal
{
    public virtual void MakeSound() { ... }
}

public class Dog : Animal
{
    // Erreur : la signature est différente (par exemple, un paramètre ajouté)
    public override void MakeSound(string sound)
    {
        Console.WriteLine(sound);
    }
}
        

3. N’utilise pas new à la place de override sans raison valable

Le mot-clé new permet de masquer la méthode de la classe de base, mais ce n’est pas une redéfinition et ça ne marche pas avec le polymorphisme dynamique. C’est un autre mécanisme, à éviter sauf si tu sais vraiment ce que tu fais.

Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION