Composition plutôt qu'héritage
L'héritage fige une taxonomie (« un Manager EST UN Employé ») qui se fissure au premier cas réel (le stagiaire ?
Prérequis : cours 1.1-1.2 ; héritage et composition, encapsulation.
Pourquoi
L'héritage fige une taxonomie (« un Manager EST UN Employé ») qui se fissure au premier cas réel (le stagiaire ? le prestataire ? le robot ?). La composition assemble des capacités : ça survit au réel.
Concepts
- Héritage : relation EST-UN, couplage fort à la classe mère (ses changements cassent les filles, fragilité du fragile base class). Bon pour : hiérarchies stables et vraiment taxonomiques (rare).
- Composition : relation A-UN (un Order A UNE stratégie de paiement, UNE politique de remise). Capacités interchangeables, testables séparément.
- Délégation : l'objet expose une capacité en la confiant à un composant interne — sans exposer le composant.
Exemple : le piège classique
// Héritage qui casse : Carré extends Rectangle (LSP !) — setWidth casse l'invariant du carré
// Composition qui tient :
function makeNotifier({ channels }) {
return { notify(msg) { channels.forEach(c => c.send(msg)); } };
}
// Email, SMS, push : des canaux branchés, pas des sous-classes
Cas réel
Jeu avec Enemy extends Character extends Entity : le boss volant + nageant force des overrides absurdes (swim() { throw … }). Refactor en composants (Movable, Damageable, Flyable) branchés par entité : 3 semaines de clarté contre 6 mois de hiérarchie.
Pièges
- « Réutiliser » par héritage : la réutilisation par héritage couple ; par composition, elle libère.
- Profondeur > 2-3 niveaux : chaque niveau multiplie les surprises. Aplatir.
- Interfaces + composition : le duo gagnant (contrat + assemblage).
À retenir
EST-UN fragile, A-UN robuste ; profondeur d'héritage ≤ 2 ; composer des capacités, pas des taxonomies.