Contactez-nous

Surcharge de méthodes (method overriding)

Apprenez à surcharger (redéfinir) des méthodes en Python. Personnalisez le comportement des classes filles en fournissant une implémentation spécifique d'une méthode héritée de la classe mère.

Qu'est-ce que la surcharge de méthodes ? Définition et objectif

La surcharge de méthodes (ou "method overriding" en anglais) est un mécanisme de la programmation orientée objet qui permet à une classe fille de fournir une implémentation spécifique d'une méthode qui est déjà définie dans sa classe mère.

La méthode redéfinie dans la classe fille doit avoir le même nom, le même nombre de paramètres et les mêmes types de paramètres (ou des types compatibles) que la méthode de la classe mère. On dit que la méthode de la classe fille *surcharge* la méthode de la classe mère.

L'objectif de la surcharge de méthodes est de permettre à une classe fille de spécialiser ou de modifier le comportement hérité de la classe mère.

La surcharge de méthodes est un élément essentiel du polymorphisme (voir section suivante).

Comment surcharger une méthode : redéfinir avec le même nom

Pour surcharger une méthode, il suffit de définir une méthode avec le même nom dans la classe fille.

Exemple :

class Animal:
    def faire_du_bruit(self):
        print("...")  # Comportement générique

class Chien(Animal):
    def faire_du_bruit(self):
        print("Wouf wouf !")  # Surcharge (redéfinition) de la méthode

class Chat(Animal):
    def faire_du_bruit(self):
        print("Miaou !")  # Surcharge (redéfinition) de la méthode

Dans cet exemple, les classes `Chien` et `Chat` héritent de la classe `Animal`. Elles surchargent toutes les deux la méthode `faire_du_bruit` pour fournir un comportement spécifique à chaque type d'animal.

Lorsque vous appelez `faire_du_bruit` sur un objet `Chien`, c'est la méthode définie dans la classe `Chien` qui est exécutée. Lorsque vous appelez `faire_du_bruit` sur un objet `Chat`, c'est la méthode définie dans la classe `Chat` qui est exécutée. Si vous appelez `faire_du_bruit` sur un objet `Animal`, c'est la méthode définie dans la classe `Animal` qui est exécutée.

Appeler la méthode de la classe mère : super()

A l'intérieur de la méthode surchargée, vous pouvez appeler la méthode de la classe mère en utilisant la fonction intégrée `super()`.

Cela vous permet d'étendre le comportement de la méthode de la classe mère, plutôt que de le remplacer complètement.

Exemple :

class Animal:
    def __init__(self, nom):
        self.nom = nom

    def afficher_infos(self):
        print(f"Nom : {self.nom}")

class Chien(Animal):
    def __init__(self, nom, race):
        super().__init__(nom)
        self.race = race

    def afficher_infos(self):
        super().afficher_infos()  # Appel de la méthode de la classe mère
        print(f"Race : {self.race}")

chien = Chien("Médor", "Labrador")
chien.afficher_infos()  # Affiche :
                       # Nom : Médor
                       # Race : Labrador

Dans cet exemple, la méthode `afficher_infos` de la classe `Chien` surcharge la méthode `afficher_infos` de la classe `Animal`. Cependant, elle appelle d'abord la méthode de la classe mère avec `super().afficher_infos()`, puis ajoute des informations supplémentaires spécifiques à la classe `Chien`.

L'utilisation de `super()` est recommandée pour appeler la méthode de la classe mère, car elle rend le code plus flexible et plus facile à maintenir (en particulier en cas d'héritage multiple).

Surcharge et polymorphisme

La surcharge de méthodes est un élément clé du polymorphisme, un autre principe fondamental de la POO.

Le polymorphisme (qui signifie "plusieurs formes") permet à des objets de différentes classes d'être traités de manière uniforme s'ils implémentent une interface commune (c'est-à-dire s'ils ont des méthodes avec le même nom).

Grâce à la surcharge de méthodes, des objets de classes différentes (mais héritant d'une même classe mère) peuvent répondre différemment à un même appel de méthode.

Exemple (reprise de l'exemple `Animal`, `Chien`, `Chat`) :

animaux = [Animal("Animal générique"), Chien("Médor"), Chat("Félix")]

for animal in animaux:
    animal.faire_du_bruit()  # Appel polymorphique

# Affiche :
# ...
# Wouf wouf !
# Miaou !

Dans cet exemple, la boucle `for` itère sur une liste d'objets de types différents (`Animal`, `Chien`, `Chat`). Pourtant, on peut appeler la méthode `faire_du_bruit` sur chaque objet, sans se soucier de son type exact. C'est le polymorphisme en action : la méthode appelée dépend du type réel de l'objet à l'exécution.

Le polymorphisme, combiné à la surcharge de méthodes, permet d'écrire du code plus générique, plus flexible et plus facile à étendre.

Surcharge vs. redéfinition (vs. masquage)

Il est important de distinguer la surcharge de méthodes (overriding) de la simple redéfinition de variables ou du masquage (shadowing).

  • Surcharge de méthodes (overriding) : Une classe fille fournit une implémentation spécifique d'une *méthode* héritée de la classe mère.
  • Redéfinition de variables : Une classe fille définit une variable (attribut) avec le même nom qu'une variable de la classe mère. Cela ne pose généralement pas de problème, sauf si vous essayez d'accéder à la variable de la classe mère via `super()` (dans ce cas, il faut être prudent).
  • Masquage (shadowing) : Une variable locale (ou un paramètre de fonction) a le même nom qu'une variable globale ou qu'une variable d'une portée englobante. La variable locale masque la variable de portée supérieure. Ce n'est pas lié à l'héritage.

La surcharge de méthodes est un concept spécifique à la POO et à l'héritage, tandis que la redéfinition de variables et le masquage sont des concepts plus généraux liés à la portée des variables.