Aller au contenu

Composition

Dans la page précédente, on a vu l’héritage. Et on a aussi vu que :

  • c’est puissant
  • mais que c’est très facile d’en faire trop

Dans cette page, on va voir une alternative parfois meilleure : la composition.


Le problème avec l’héritage (rappel rapide)

L’héritage fonctionne bien quand la relation est claire :

“X est un Y”

Mais beaucoup de relations ne sont pas de ce type.

Par exemple :

  • un personnage a une arme
  • une voiture a un moteur
  • un joueur a un inventaire

L’idée de la composition

La composition repose sur une idée simple :

Au lieu de dire “X est un Y” on dit “X a un Y”

Autrement dit :

  • un objet contient un ou plusieurs autres objets
  • chaque objet garde sa responsabilité

Exemple simple

On veut modéliser une arme.

class Arme:
    def __init__(self, nom, degats):
        self.nom = nom
        self.degats = degats

Puis un personnage :

class Personnage:
    def __init__(self, nom, vie, arme):
        self.nom = nom
        self.vie = vie
        self.arme = arme

Ici :

  • Personnage a une arme
  • Arme reste une classe indépendante
  • aucune hiérarchie artificielle

Utiliser les objets ensemble

epee = Arme("Épée", 10)
p = Personnage("Alice", 100, epee)

print(p.arme.nom)
print(p.arme.degats)

Chaque objet fait ce qu’il sait faire. On assemble les briques.


Pourquoi la composition est souvent meilleure

La composition permet :

  • plus de flexibilité
  • moins de dépendances rigides
  • des classes plus simples
  • des changements plus faciles

Par exemple :

  • changer d’arme sans toucher à Personnage
  • ajouter un nouveau type d’arme sans modifier le reste
  • tester chaque classe séparément

Composition et évolution du code

Avec la composition, il est très facile de faire évoluer un programme.

Exemple :

p.arme = Arme("Arc", 7)

Aucun héritage compliqué. Aucune refonte de hiérarchie. On remplace simplement un objet par un autre.


Héritage ou composition ?

La règle pratique est la suivante :

Question Bonne réponse
X est-il un cas particulier de Y ? Héritage
X possède-t-il un Y ? Composition
Est-ce que la relation peut changer dans le temps ? Composition
Est-ce que l’héritage semble “forcé” ? Composition

En cas de doute :

préférez la composition.


Quizz

Quelle relation doit être modélisée par de la composition ?
- Un chat est un animal
- *Un joueur a un inventaire
- Un carré est un rectangle
- Un mage est un personnage
> La composition correspond à une relation “a un”.

Exercice pratique

On veut modéliser un lecteur de musique.

Créez une classe Chanson qui contient :

  • un titre
  • un artiste
  • une durée

Créez une classe LecteurMusique qui :

  • contient une chanson en cours et un volume de son
  • possède une méthode jouer() qui affiche "Lecture de <titre> par <artiste> au volume <volume>"

Créez plusieurs chansons, puis :

  • réglez le volume
  • changez la chanson du lecteur
  • appelez jouer() à chaque changement de chanson

En résumé

La composition permet de :

  • assembler des objets entre eux
  • éviter des hiérarchies bancales
  • écrire du code plus flexible et plus propre

L’héritage n’est pas mauvais, mais la composition est souvent le meilleur choix par défaut.

Dans la page suivante, on va mettre tout ça en pratique avec un nouveau projet plus ambitieux.