Plus facile à lire avec un fond crème, une teinte, plus de contraste ou un texte plus grand ? Choisissez vos couleurs et votre texte, une fois pour toutes les pages.

Leçon gratuite

Composition contre héritage

Après cette leçon: Je peux choisir la composition plutôt que l’héritage et dire pourquoi.

Leçon de 55 min4 commandesLab Linux du quotidien : la trentaine de commandes que les ingénieurs tapent de tête

Qu’est-ce que la composition en programmation objet ?

La composition consiste à construire un objet à partir d’autres objets qu’il contient et qu’il utilise. On dit qu’il a une partie, au lieu de dire qu’il est une version d’une autre classe. Elle rend un programme plus facile à changer qu’une grande famille de classes liées par l’héritage.

Une université prévient ses étudiants d’un cours annulé. Le message part par SMS, par courriel, ou par les deux.

À la fin de cette leçon

Remarque

Je peux choisir la composition plutôt que l’héritage et dire pourquoi.

Mots-clés

MotCe que ça veut direExemple
Compositionun objet qui en contient d’autres et les utilise
Est unla relation d’héritageun colis express est un colis
A unla relation de compositionune alerte a un canal
Délégationun objet confie un travail à la partie qu’il contient
Couplagele degré auquel une classe dépend d’une autre
Interfaceles méthodes qu’un objet promet de savoir faire

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

L’héritage enferme le choix dans la classe

Imaginez une classe AlerteSms et une classe AlerteCourriel, filles de Alerte. Chaque canal est une classe entière.

Une alerte qui doit partir par SMS et par courriel demande une troisième classe. Avec un troisième canal, il en faut sept. Le nombre de classes explose.

Une alerte reçoit son canal

Au lieu d’hériter, Alerte reçoit un objet canal dans son constructeur et le range dans un attribut. Pour prévenir, elle lui délègue le travail : self.canal.envoyer(texte).

Chaque canal est une petite classe à part. Changer de canal, c’est donner un autre objet.

Une alerte qui contient un canal

Code: python
class CanalSms:
    def envoyer(self, texte):
        return "SMS : " + texte


class CanalCourriel:
    def envoyer(self, texte):
        return "Courriel : " + texte


class Alerte:
    def __init__(self, canal):
        self.canal = canal

    def prevenir(self, texte):
        return self.canal.envoyer(texte)


alerte = Alerte(CanalSms())
print(alerte.prevenir("Cours annulé"))
alerte.canal = CanalCourriel()
print(alerte.prevenir("Cours annulé"))

Créer un dossier pour les essais

Commande
mkdir -p essais

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.

Écrire l’alerte et ses deux canaux

Commande
printf 'class CanalSms:\n    def envoyer(self, texte):\n        return "SMS : " + texte\n\n\nclass CanalCourriel:\n    def envoyer(self, texte):\n        return "Courriel : " + texte\n\n\nclass Alerte:\n    def __init__(self, canal):\n        self.canal = canal\n\n    def prevenir(self, texte):\n        return self.canal.envoyer(texte)\n' > essais/alerte.py

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.

Prévenir par SMS puis par courriel

Commande
PYTHONPATH=essais python3 -c "from alerte import Alerte, CanalSms, CanalCourriel; a = Alerte(CanalSms()); print(a.prevenir('Cours annule')); a.canal = CanalCourriel(); print(a.prevenir('Cours annule'))"

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.

Comment choisir entre hériter et composer

Posez la question : « B est-il vraiment un A, dans tous les cas, pour toujours ? ». Si oui, l’héritage est possible.

Si B utilise A, ou si la partie doit pouvoir changer en cours de route, composez. Dans le doute, composez : une partie se remplace, une classe mère ne se quitte pas.

Héritage et composition côte à côte

QuestionHéritageComposition
Relationest una un
Quand le choix se faità l’écriture de la classeà l’exécution, en donnant un objet
Changer de comportementécrire une nouvelle classedonner une autre partie
Couplage avec l’autre classefortfaible : seule la méthode compte

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Lire la classe de la partie contenue

Commande
PYTHONPATH=essais python3 -c "from alerte import Alerte, CanalCourriel; a = Alerte(CanalCourriel()); print(type(a.canal).__name__)"

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 croient que la composition est une façon plus longue d’écrire l’héritage. Ce sont deux relations différentes. L’héritage fixe la parenté pour toujours. La composition laisse changer la partie quand on le veut, même pendant l’exécution.

Écrire une alerte à plusieurs canaux

Dans le devoir, vous écrivez la classe Alerte. Elle range une liste de canaux. ajouter_canal(canal) en ajoute un, retirer_canal(canal) en enlève un.

prevenir(texte) envoie le texte à chaque canal et rend la liste des réponses, dans l’ordre. Les tests lui donnent leurs propres faux canaux.

À propos de ce labo et de sa source: Lab Linux du quotidien : la trentaine de commandes que les ingénieurs tapent de tête

Vous enseignez à une classe ? Proposez ce module à vos étudiants avec un guide de l'enseignant, des devoirs corrigés et un laboratoire pour chaque étudiant.