Qu’est-ce que l’héritage en programmation objet ?
L’héritage permet à une classe de reprendre les attributs et les méthodes d’une autre classe, puis d’y ajouter ou d’en changer. Il évite de recopier le même code dans plusieurs classes qui se ressemblent.
Un service de livraison envoie des colis ordinaires, express et fragiles. Tous ont un poids et un coût, mais le coût ne se calcule pas de la même façon.
À la fin de cette leçon
Remarque
Je peux réutiliser du code par héritage et faire appeler la même méthode sur des objets de classes différentes.
Mots-clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Héritage | le fait qu’une classe reprenne ce que fait une autre classe | |
| Classe mère | la classe dont on hérite | class Colis: |
| Classe fille | la classe qui hérite | class ColisExpress(Colis): |
| Redéfinition | une méthode de la fille qui remplace celle de la mère | |
| super() | l’appel de la méthode de la classe mère | |
| Polymorphisme | le même appel qui fait des choses différentes selon l’objet |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Recopier une classe est le chemin des fautes
Un colis ordinaire coûte 500 centimes plus 100 par kilo. Un colis express coûte la même chose plus 1 000.
Si vous recopiez la classe Colis pour écrire ColisExpress, le jour où le tarif de base change, il faut penser à corriger les deux. On en oublie toujours une.
Une classe fille hérite de sa mère
class Colis:
def __init__(self, poids_kg):
self.poids_kg = poids_kg
def cout(self):
return 500 + 100 * self.poids_kg
class ColisExpress(Colis):
pass
colis = ColisExpress(2)
print(colis.poids_kg, colis.cout())
Une fille redéfinit une méthode et appelle super()
ColisExpress(Colis) reprend tout de Colis, sans rien recopier. Pour changer le coût, la fille écrit une méthode du même nom : c’est la redéfinition.
Dans cette méthode, super().cout() appelle la méthode de la mère. La fille ajoute son supplément au coût de base.
Ajouter le supplément express avec super
class Colis:
def __init__(self, poids_kg):
self.poids_kg = poids_kg
def cout(self):
return 500 + 100 * self.poids_kg
class ColisExpress(Colis):
def cout(self):
return super().cout() + 1000
print(Colis(2).cout(), ColisExpress(2).cout())
Créer un dossier pour les essais
mkdir -p essaisAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire la famille de colis
printf 'class Colis:\n def __init__(self, poids_kg):\n self.poids_kg = poids_kg\n\n def cout(self):\n return 500 + 100 * self.poids_kg\n\n\nclass ColisExpress(Colis):\n def cout(self):\n return super().cout() + 1000\n\n\nclass ColisFragile(Colis):\n def cout(self):\n return super().cout() + 300\n' > essais/colis.pyAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Comparer les trois coûts pour 2 kilos
PYTHONPATH=essais python3 -c "from colis import Colis, ColisExpress, ColisFragile; print(Colis(2).cout(), ColisExpress(2).cout(), ColisFragile(2).cout())"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Le polymorphisme : un appel, plusieurs comportements
Parcourez une liste qui mélange des colis de trois classes. À chaque tour, vous écrivez colis.cout() et vous n’avez pas à vous demander de quelle classe il s’agit.
Chaque objet répond avec sa propre version de la méthode. C’est le polymorphisme. Il supprime les longues suites de if sur le type.
Écrire un programme qui parcourt un lot
printf 'from colis import Colis, ColisExpress, ColisFragile\n\nlot = [Colis(1), ColisExpress(1), ColisFragile(1)]\nfor colis in lot:\n print(type(colis).__name__, colis.cout())\n' > essais/lot.pyAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Lancer le programme du lot
python3 essais/lot.pyAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Une fille est aussi une mère
PYTHONPATH=essais python3 -c "from colis import Colis, ColisExpress; print(isinstance(ColisExpress(1), Colis), isinstance(Colis(1), ColisExpress))"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Erreur fréquente
Attention
Beaucoup pensent qu’il faut hériter dès que deux classes partagent du code. L’héritage dit « est un » : un colis express est un colis. Si la phrase est fausse, n’héritez pas. Vous verrez à la leçon suivante quoi faire à la place.
Écrire une famille de colis
Dans le devoir, la classe Colis est déjà écrite. Vous écrivez ColisExpress (1 000 centimes en plus) et ColisFragile (300 en plus), en appelant super().
Vous écrivez aussi total_cout(colis), qui additionne le coût d’une liste de colis de classes mêlées.