Polymorphisme
En Python, le polymorphisme se manifeste principalement par la redéfinition de méthode (method overriding) : une classe enfant réimplémente une méthode héritée de sa classe mère pour adapter son comportement à ses besoins spécifiques.
| Forme de polymorphisme | Description | Mécanisme Python |
|---|---|---|
| Redéfinition (overriding) | La sous-classe réimplémente une méthode du parent | Même nom de méthode dans la sous-classe |
| Duck typing | Tout objet ayant la méthode attendue est accepté | Pas de vérification de type explicite |
| Fonctions polymorphes | Une fonction accepte tout objet ayant une méthode donnée | Appel générique obj.methode() |
Redéfinition de méthode (Method Overriding)
class Parent:
def methode(self):
# implémentation par défaut
...
class Enfant(Parent):
def methode(self): # redéfinition — même nom
# implémentation spécifique à Enfant
...Exemple — Hiérarchie Personne → Etudiant / Professeur
class Personne:
def __init__(self, nom):
self.nom = nom
def afficher(self):
print(f"Je suis une personne. Nom : {self.nom}")
class Etudiant(Personne):
def __init__(self, nom, cne):
super().__init__(nom)
self.cne = cne
def afficher(self): # redéfinition de afficher()
print(f"Je suis un étudiant. Nom : {self.nom} | CNE : {self.cne}")
class Professeur(Personne):
def __init__(self, nom, ppr):
super().__init__(nom)
self.ppr = ppr
def afficher(self): # redéfinition de afficher()
print(f"Je suis un professeur. Nom : {self.nom} | PPR : {self.ppr}")
# Polymorphisme en action — même appel, comportements différents
personnes = [
Etudiant('Kayouh', 123444),
Professeur('ESSADDOUKI', 123123123),
Personne('Alami')
]
for obj in personnes:
obj.afficher() # appelle la version propre à chaque classeJe suis un étudiant. Nom : Kayouh | CNE : 123444 Je suis un professeur. Nom : ESSADDOUKI | PPR : 123123123 Je suis une personne. Nom : Alami
NomClasse.__mro__.print(Etudiant.__mro__)
# (, , )Polymorphisme avec des fonctions
Python permet de créer des fonctions polymorphes : des fonctions qui acceptent n'importe quel objet possédant une méthode donnée, sans se soucier de son type réel. C'est le principe du duck typing : « Si ça marche comme un canard et que ça fait coin-coin, c'est un canard. »
Exemple — Fonction polymorphe afficher_infos()
def afficher_infos(obj):
"""Fonctionne avec tout objet ayant une méthode afficher()."""
print(type(obj).__name__, "→", end=" ")
obj.afficher()
etd = Etudiant('Kayouh', 123444)
prf = Professeur('ESSADDOUKI', 123123123)
per = Personne('Alami')
afficher_infos(etd)
afficher_infos(prf)
afficher_infos(per)Etudiant → Je suis un étudiant. Nom : Kayouh | CNE : 123444 Professeur → Je suis un professeur. Nom : ESSADDOUKI | PPR : 123123123 Personne → Je suis une personne. Nom : Alami
Exemple — Duck typing avec classes sans lien d'héritage
Le polymorphisme en Python ne nécessite pas obligatoirement l'héritage. Deux classes totalement indépendantes peuvent être utilisées de façon polymorphe si elles partagent le même nom de méthode.
class Chien:
def parler(self):
print("Woof !")
class Chat:
def parler(self):
print("Miaou !")
class Perroquet:
def parler(self):
print("Bonjour !")
def faire_parler(animal):
animal.parler() # fonctionne pour tout objet ayant parler()
animaux = [Chien(), Chat(), Perroquet()]
for a in animaux:
faire_parler(a)Woof ! Miaou ! Bonjour !
Aller plus loin — Méthodes abstraites
Pour forcer les sous-classes à redéfinir une méthode, Python propose le module abc (Abstract Base Classes). Une méthode abstraite déclarée dans la classe mère doit obligatoirement être implémentée dans chaque sous-classe.
from abc import ABC, abstractmethod
class Personne(ABC):
def __init__(self, nom):
self.nom = nom
@abstractmethod
def afficher(self):
"""Chaque sous-classe DOIT implémenter cette méthode."""
pass
class Etudiant(Personne):
def __init__(self, nom, cne):
super().__init__(nom)
self.cne = cne
def afficher(self): # obligatoire
print(f"Étudiant : {self.nom} | CNE : {self.cne}")
# Personne() → TypeError : impossible d'instancier une classe abstraite
etd = Etudiant('Kayouh', 123444)
etd.afficher()Étudiant : Kayouh | CNE : 123444
Personne()) lève une TypeError. Cela garantit que toutes les sous-classes implémentent bien les méthodes requises.Récapitulatif
| Concept | Rôle | Exemple |
|---|---|---|
| Redéfinition | Adapter le comportement d'une méthode héritée | afficher() dans Etudiant |
| Duck typing | Appeler une méthode sans vérifier le type | obj.afficher() dans une boucle |
| Fonction polymorphe | Accepter tout objet ayant la méthode attendue | afficher_infos(obj) |
| Classe abstraite | Forcer la redéfinition dans les sous-classes | @abstractmethod + ABC |
| MRO | Ordre de recherche des méthodes | Classe.__mro__ |