Lesson 6/6 10 min

Polymorphism

One message, different responses depending on the object. The magic of interfaces, explained with an interactive zoo where each animal answers in its own way.

FR EN

Un même mot, des réponses différentes

À la leçon précédente, tu as appelé demarrer() sur deux moteurs différents : l'un faisait « Vroum », l'autre le silence. Le même appel, des comportements différents. Ce petit miracle a un nom : le polymorphisme (du grec « plusieurs formes »).

L'idée : plusieurs objets différents comprennent le même message (la même méthode), et chacun y répond à sa manière. Celui qui appelle n'a pas besoin de savoir à qui il parle : il envoie le message, l'objet se débrouille.

L'exemple qui parle : le zoo

Imagine des animaux : un chien, un chat, un canard. Tous savent parler(), mais le résultat diffère. Si tu as une liste d'animaux et que tu veux les faire crier, tu écris une seule boucle qui appelle parler() sur chacun, sans te soucier de l'espèce :

Une même boucle appelle la méthode parler() sur un chien, un chat et un canard ; chacun répond par un son différent. Un appel, trois réponses. la boucle a.parler() Chien → « Wouf ! » Chat → « Miaou ! » Canard → « Coin ! » Un seul appel, autant de réponses que d'objets.
La boucle envoie le même message parler() ; chaque objet répond à sa façon.
classe Chien:  public parler(): retourne "Wouf !"
classe Chat:   public parler(): retourne "Miaou !"
classe Canard: public parler(): retourne "Coin coin !"

animaux = [new Chien(), new Chat(), new Canard()]

// UNE seule boucle, qui ignore l'espèce : c'est ça, le polymorphisme
pour chaque a dans animaux:
    afficher(a.parler())   // "Wouf !", "Miaou !", "Coin coin !"

La boucle ne contient aucun si c'est un chien… sinon si c'est un chat…. Elle envoie parler() et fait confiance à chaque objet pour répondre correctement.

Pourquoi c'est puissant : le contrat

Pour que ça marche, tous les animaux doivent respecter le même contrat : « je sais parler() ». Ce contrat partagé s'appelle une interface (ou une classe abstraite). Tant qu'un objet respecte le contrat, le reste du code l'accepte sans le connaître.

Le vrai bénéfice : on ajoute un nouveau cas sans toucher au code existant. Demain tu ajoutes un Mouton qui sait parler() ? La boucle le gère sans une seule modification. C'est ce qui rend un programme extensible : on branche de nouvelles pièces, on ne réécrit pas les anciennes.

Le zoo en vrai (fais-les parler, ajoute un mouton)

Chaque animal est un objet avec sa propre méthode parler(). Le bouton lance une seule boucle sur toute la liste. Ajoute un mouton : la même boucle le fait parler, sans aucune modification.

Rappel libre

Sans remonter dans la leçon : avec tes mots, qu'est-ce que le polymorphisme, et qu'est-ce que la boucle animaux.forEach(a => a.parler()) n'a justement pas besoin de savoir ?

Le polymorphisme, c'est un même message (la méthode parler()) auquel chaque objet répond à sa façon : Chien renvoie « Wouf ! », Chat « Miaou ! », etc. La boucle n'a pas besoin de connaître l'espèce de chaque a : elle envoie parler() et fait confiance au contrat partagé. Pas de if c'est un chien… sinon si c'est un chat….
Qu'est-ce que le polymorphisme ?
Quel est le principal bénéfice du polymorphisme ?
Accepter ou rejeter le code de l'IA

Tu as demandé à l'IA une fonction qui fait crier un animal. Elle te propose ceci. Ton rôle de relecteur : l'accepter telle quelle ou la rejeter, et dire pourquoi.

function faireCrier(animal) {
  if (animal.espece === 'chien')  return 'Wouf !';
  else if (animal.espece === 'chat')   return 'Miaou !';
  else if (animal.espece === 'canard') return 'Coin coin !';
  // ... un else if de plus à chaque nouvel animal
}
À rejeter. C'est exactement l'anti-pattern que le polymorphisme élimine : une cascade de if / else if qui teste l'espèce. Le défaut n'est pas qu'elle plante (elle marche), mais qu'elle oblige à rouvrir et modifier cette fonction à chaque nouvel animal. La bonne version donne à chaque classe sa propre méthode parler() et appelle simplement animal.parler() : ajouter un Mouton ne touche plus une ligne du code appelant.
Bravo, tu as fini le cours

Six piliers : objet/classe, encapsulation, héritage, composition, polymorphisme. Tu as maintenant le vocabulaire et les réflexes de la POO, indépendamment du langage. La suite logique : les appliquer pour de vrai, en PHP ou en JavaScript.

Revoir le cours POO →

One word, different answers

In the previous lesson, you called demarrer() on two different engines: one went "Vroum", the other stayed silent. The same call, different behaviors. That little miracle has a name: polymorphism (Greek for "many forms").

The idea: several different objects understand the same message (the same method), and each answers in its own way. The caller doesn't need to know who it's talking to: it sends the message, the object handles it.

The telling example: the zoo

Picture some animals: a dog, a cat, a duck. They all know how to parler() (speak), but the result differs. If you have a list of animals and want to make them all speak, you write a single loop that calls parler() on each, without caring about the species:

A single loop calls the parler() method on a dog, a cat and a duck; each answers with a different sound. One call, three answers. the loop a.parler() Chien → "Wouf !" Chat → "Miaou !" Canard → "Coin !" One call, as many answers as there are objects.
The loop sends the same message parler(); each object answers in its own way.
class Chien:  public parler(): return "Wouf !"
class Chat:   public parler(): return "Miaou !"
class Canard: public parler(): return "Coin coin !"

animaux = [new Chien(), new Chat(), new Canard()]

// ONE loop, ignoring the species: that's polymorphism
for each a in animaux:
    print(a.parler())   // "Wouf !", "Miaou !", "Coin coin !"

The loop contains no if it's a dog… else if it's a cat…. It sends parler() and trusts each object to answer correctly.

Why it's powerful: the contract

For this to work, all animals must honor the same contract: "I know how to parler()". That shared contract is called an interface (or an abstract class). As long as an object honors the contract, the rest of the code accepts it without knowing it.

The real benefit: you add a new case without touching the existing code. Tomorrow you add a Mouton (sheep) that knows how to parler()? The loop handles it with zero changes. That's what makes a program extensible: you plug in new parts, you don't rewrite the old ones.

The zoo for real (make them speak, add a sheep)

Each animal is an object with its own parler() method. The button runs a single loop over the whole list. Add a sheep: the same loop makes it speak, with no change at all.

Well done, you finished the course

Six pillars: object/class, encapsulation, inheritance, composition, polymorphism. You now have the vocabulary and reflexes of OOP, independent of any language. The logical next step: apply them for real, in PHP or JavaScript.

Back to the OOP course →
Next step

You've covered the big OOP principles: object, class, encapsulation, inheritance, composition, polymorphism. Now the hands-on part in PHP, where you write real classes you actually run.

Object-oriented PHP →
Besoin d'un développeur pour votre projet ?

Réponse sous 24h · Sans engagement