Héritage¶
L’héritage est probablement le concept le plus mal compris de la programmation orientée objet.
C’est puissant, oui.
Mais mal utilisé, ça rend le code :
- compliqué
- rigide
- difficile à faire évoluer
Donc dans cette page, on va faire les choses proprement et calmement.
L’idée de base¶
L’héritage permet de créer une classe à partir d’une autre classe.
On parle de :
- classe parent (ou classe mère)
- classe enfant
La classe enfant :
- récupère les attributs
- récupère les méthodes
- peut en ajouter ou en modifier
Exemple simple¶
Reprenons notre exemple de jeu.
class Personnage:
def __init__(self, nom, vie):
self.nom = nom
self.vie = vie
def attaquer(self):
print("Le personnage attaque")
On peut maintenant créer une classe plus spécialisée :
class Guerrier(Personnage):
pass
Guerrier est une classe :
- plus spécifique
- qui est un
Personnage
Héritage = “est un”¶
C’est la règle d’or :
Si une classe n’est pas un cas particulier de l’autre, alors l’héritage est une mauvaise idée.
- Un guerrier est un personnage → OK
- Une arme n’est pas un personnage → pas OK
Si la phrase “X est un Y” ne fonctionne pas naturellement, il ne faut probablement pas utiliser l’héritage.
Redéfinir une méthode¶
Une classe enfant peut redéfinir une méthode héritée.
class Guerrier(Personnage):
def attaquer(self):
print(f"{self.nom} attaque avec son épée")
Maintenant :
p = Personnage("Alice", 100)
g = Guerrier("Bob", 120)
p.attaquer()
g.attaquer()
Affiche :
Le personnage attaque
Bob attaque avec son épée
Appeler le constructeur parent : super()¶
Si la classe enfant a besoin d’un constructeur,
il faut appeler celui de la classe parente, à l'aide du mot clef super().
class Guerrier(Personnage):
def __init__(self, nom, vie, force):
super().__init__(nom, vie)
self.force = force
Quizz¶
Laquelle de ces relations justifie un héritage ?
- Une voiture a un moteur
- Un joueur dispose d'un inventaire
- *Un mage est un personnage
- Un personnage attaque avec une arme
> L’héritage correspond à une relation “est un”.
Le polymorphisme¶
Regardez ce code :
personnages = [
Personnage("Alice", 100),
Guerrier("Bob", 120, 10)
]
for p in personnages:
p.attaquer()
Python ne se demande pas :
- si
pest unPersonnage - ou un
Guerrier
Il appelle simplement la bonne méthode.
C’est ce qu’on appelle le polymorphisme :
même méthode, comportement différent
Composition vs héritage (aperçu)¶
Quand on veut dire :
“X a un Y”
On parle de composition, pas d’héritage.
class Personnage:
def __init__(self, nom, vie, arme):
self.arme = arme
On verra ça plus en détail plus tard, mais gardez ça en tête :
“a un” ≠ “est un”
Exercice pratique¶
On veut modéliser différents types de notifications dans une application.
Créez une classe Notification qui :
- possède une heure d'envoi
- possède une méthode `envoyer()` qui affiche un message générique (du genre `vous avez reçu une notification à X heure`).
Créez une classe NotificationEmail qui hérite de Notification et qui :
- possède un expéditeur
- redéfinit la méthode
envoyer()pour afficher
Vous avez reçu un e-mail de la part de X à Y heure
Créez une classe NotificationBanque qui hérite de Notification et qui :
- possède un montant
- redéfinit la méthode
envoyer()pour afficher
Vous avez effectué un paiement de X euros à Y heure
Créez une liste contenant plusieurs notifications de types différents
(NotificationEmail, NotificationSMS, etc.)
Parcourez cette liste et appelez envoyer() sur chaque notification.
L’objectif de cet exercice est de comprendre que : - plusieurs classes peuvent hériter d’une même classe parente - une même méthode peut produire des comportements différents - le reste du code n’a pas besoin de connaître le type exact de l’objet
Ce n’est pas l’exercice le plus fun du monde,
mais c’est un excellent test pour savoir si l’héritage est bien compris.
En résumé¶
L’héritage permet :
- de spécialiser une classe existante
- de réutiliser du code
- d’écrire du code plus générique
Mais :
- ce n’est pas obligatoire
- ce n’est pas toujours une bonne idée
- mal utilisé, ça complique tout
Dans la page suivante, on va voir une alternative parfois meilleure : la composition, et pourquoi elle est si importante.