À propos de ce cours
Chapitre 16 — La programmation orientée objet · 16.7 Polymorphisme et composition
Nouvelle leçon : le polymorphisme et la composition sont les deux idées qui rendent la POO vraiment utile, et le TP du panier d'achat les utilise toutes les deux.
• expliquer le polymorphisme et en tirer parti pour éviter les
if sur le type ;• définir une méthode « à redéfinir » dans une classe parent ;
• construire un objet à partir d'autres objets (composition) ;
• choisir entre héritage (« est un ») et composition (« a un »).

Figure 1 — Deux façons d'organiser des objets.
1. Le polymorphisme
Polymorphisme signifie « plusieurs formes » : le même appel de méthode produit un comportement adapté à chaque objet. Le code qui appelle n'a pas besoin de connaître le type exact de l'objet.
class Forme {
aire() {
throw new Error(`${this.constructor.name} doit définir aire()`);
}
decrire() {
return `${this.constructor.name} d'aire ${this.aire().toFixed(2)}`;
}
}
class Rectangle extends Forme {
constructor(l, h) { super(); this.l = l; this.h = h; }
aire() { return this.l * this.h; }
}
class Cercle extends Forme {
constructor(r) { super(); this.r = r; }
aire() { return Math.PI * this.r ** 2; }
}
class Triangle extends Forme {
constructor(b, h) { super(); this.b = b; this.h = h; }
// aire() oubliée !
}
// POLYMORPHISME : le même appel, un comportement adapté à chaque objet
const formes = [new Rectangle(3, 4), new Cercle(1), new Rectangle(2, 2)];
for (const f of formes) console.log(f.decrire());
const total = formes.reduce((s, f) => s + f.aire(), 0);
console.log("Aire totale :", total.toFixed(2));
try {
new Triangle(3, 4).decrire();
} catch (e) {
console.log("Erreur :", e.message);
}
Résultat dans la console
Rectangle d'aire 12.00 Cercle d'aire 3.14 Rectangle d'aire 4.00 Aire totale : 19.14 Erreur : Triangle doit définir aire()
decrire()est écrite une seule fois, dansForme, mais appellethis.aire()qui est différente pour chaque forme.- La boucle ne contient aucun
if (f instanceof Cercle): ajouter une nouvelle forme ne demande de modifier aucun code existant. Formelève une erreur claire si un enfant oublie de redéfiniraire(): c'est une méthode « abstraite ».
// ✗ Sans polymorphisme : chaque nouveau type oblige à modifier cette fonction
function aire(forme) {
if (forme.type === "rectangle") return forme.l * forme.h;
if (forme.type === "cercle") return Math.PI * forme.r ** 2;
// … et ainsi de suite
}
2. La composition
La composition consiste à construire un objet en y plaçant d'autres objets, qui font chacun une partie du travail. L'objet principal délègue: il appelle les méthodes de ses composants.
// COMPOSITION : un objet « A UN » autre objet, au lieu « d'ÊTRE UN »
class Moteur {
constructor(puissance) {
this.puissance = puissance;
this.allume = false;
}
demarrer() {
this.allume = true;
return `Moteur ${this.puissance} ch démarré`;
}
}
class GPS {
itineraire(destination) {
return `Itinéraire calculé vers ${destination}`;
}
}
class Voiture {
constructor(marque, puissance, avecGPS = false) {
this.marque = marque;
this.moteur = new Moteur(puissance); // une voiture A UN moteur
this.gps = avecGPS ? new GPS() : null; // et peut-être un GPS
}
partir(destination) {
const etapes = [this.moteur.demarrer()]; // elle DÉLÈGUE au moteur
if (this.gps) etapes.push(this.gps.itineraire(destination));
return `${this.marque} : ${etapes.join(", ")}`;
}
}
console.log(new Voiture("Clio", 90, true).partir("Sousse"));
console.log(new Voiture("Twingo", 65).partir("Bizerte"));
Résultat dans la console
Clio : Moteur 90 ch démarré, Itinéraire calculé vers Sousse Twingo : Moteur 65 ch démarré
3. Héritage ou composition ?
| Héritage | Composition | |
|---|---|---|
| Relation | « est un » (un livre est un produit) | « a un » (une voiture a un moteur) |
| Lien | fort et fixé à l'écriture | souple : on peut changer de composant |
| Risque | hiérarchies profondes et fragiles | un peu plus de code de délégation |
| Exemple du TP | ProduitPhysique extends Produit | un Panier contient des LignePanier |
Règle souvent citée : « préférez la composition à l'héritage ». N'héritez que si la relation « est un » est vraie et durable.
• Polymorphisme : même appel, comportement propre à chaque classe ; pas de
if sur le type.• Une méthode parent qui lève une erreur force les enfants à la redéfinir.
• Composition : un objet contient d'autres objets et leur délègue le travail.
• « est un » → héritage ; « a un » → composition ; dans le doute, composition.
🛠 Activité 7 — Préparer le panier d'achat
Mission : Avant le TP, entraînez-vous sur un modèle réduit : une commande de restaurant.
Questions pour avancer (répondez dans votre compte rendu, puis appliquez dans votre projet) :
- Un restaurant vend des
Plats, desBoissons et desDesserts. Chacun a un nom et un prix, mais les boissons sont taxées à 7 % et le reste à 19 %. Quelle méthode sera polymorphe ? Où la déclarez-vous ? - Une
Commandecontient des articles et une table. Est-ce un héritage ou une composition ? Dessinez le diagramme des classes avec les flèches « est un » et « a un ». - Écrivez
Commande.total()sans aucunifniinstanceof. Comment faites-vous ? - Ajoutez un nouveau type
Menu(plat + boisson + dessert à prix réduit). Combien de fichiers ou de classes existants avez-vous dû modifier ? UnMenuest-il un article, contient-il des articles, ou les deux ? - Un collègue propose
class Commande extends Arraypour profiter depushetmap. Quels sont les risques ? Que proposez-vous à la place ?
Je vérifie / je rends :
- ☐ Le diagramme des classes.
- ☐ Le code de la commande et la démonstration de l'ajout de
Menu.
← 16.6 Les prototypes : ce qui se cache derrière les classes16.8 TP 16 : Gérer un panier d'achat en POO →