Menu
Français

Héritage en JavaScript : extends, super et override

Comment fonctionne l'héritage des classes JavaScript : le mot-clé extends, l'appel à super, la redéfinition de méthodes, et quand lui préférer la composition.

Une classe qui s'appuie sur une autre

L'héritage en JavaScript permet à une classe de partir du modèle d'une autre classe et de l'étendre. Tu récupères gratuitement tous les champs et méthodes de la classe parente, et tu peux ajouter ou modifier ce que tu veux :

index.js
Output
Click Run to see the output here.

Dog extends Animal veut dire : « un Dog est un Animal, avec un petit truc en plus ». rex n'a pas de méthode speak à lui, mais la recherche retombe sur Animal, qui en possède une. Ce mécanisme de repli, c'est tout le principe de l'héritage en JavaScript — du chaînage de prototypes avec une syntaxe plus agréable.

super dans le constructeur

Une sous-classe qui définit son propre constructeur doit respecter une règle non négociable : appeler super(...) avant de toucher à this. super exécute le constructeur de la classe parente, et c'est justement lui qui crée et initialise réellement l'objet :

index.js
Output
Click Run to see the output here.

Si tu oublies la ligne super(name), tu te prends un ReferenceError dès que tu essaies de lire ou d'écrire sur this. Le moteur refuse catégoriquement de te donner accès à this tant que le parent n'est pas passé avant.

Quand une sous-classe ne déclare pas son propre constructeur, JavaScript en génère un automatiquement qui transmet tous les arguments à super — tu n'as donc besoin d'en écrire un que si tu ajoutes des champs ou que tu fais un peu de préparation en plus.

Redéfinir une méthode en JavaScript

Une sous-classe peut redéfinir n'importe quelle méthode dont elle hérite. C'est la version la plus proche dans la chaîne qui l'emporte :

index.js
Output
Click Run to see the output here.

Pas de magie ici : quand tu appelles speak() sur un Dog, le moteur cherche speak sur l'instance, puis sur Dog.prototype, le trouve, et s'arrête là. Il n'ira jamais jusqu'à Animal.prototype.

Étendre plutôt que remplacer : super.method()

Parfois, tu ne veux pas remplacer la méthode du parent — tu veux simplement y ajouter quelque chose. super.method(...) permet d'appeler la version du parent depuis la méthode redéfinie :

index.js
Output
Click Run to see the output here.

C'est précisément là que l'héritage en JavaScript prend tout son sens : la sous-classe réutilise la logique du parent au lieu de la recopier. Si Animal.describe évolue plus tard, Dog.describe en profite automatiquement.

super fonctionne dans n'importe quelle méthode, pas seulement dans le constructeur. Il fait toujours référence à la version de la classe parente de ce que tu appelles.

instanceof et la chaîne de prototypes

instanceof vérifie si la chaîne de prototypes d'un objet inclut une classe donnée. Toute instance d'une sous-classe est également une instance de ses classes parentes :

index.js
Output
Click Run to see the output here.

Les quatre renvoient true. La chaîne de prototypes suit l'ordre Puppy -> Dog -> Animal -> Object, et instanceof la parcourt de bout en bout. Pratique pour vérifier un type, même si en vrai vous y toucherez moins souvent que prévu — la plupart du temps, le code appelle juste des méthodes et laisse le polymorphisme faire le boulot.

Un exemple un peu plus poussé

Voici un schéma classique : une classe de base qui regroupe la logique commune, et quelques sous-classes qui viennent la spécialiser.

index.js
Output
Click Run to see the output here.

Remarque que describe vit sur Shape et qu'on n'a jamais besoin de la réécrire — elle se contente d'appeler this.area(), qui résout vers la bonne sous-classe à l'exécution. C'est ça, le polymorphisme : un même point d'appel, des comportements différents selon l'objet réel.

Héritage ou composition : que choisir ?

L'héritage est séduisant parce qu'il donne l'impression d'aller vite — une seule ligne et on hérite d'une tonne de méthodes. Mais il vieillit mal dès que les hiérarchies grossissent.

La règle en pratique : utilise extends quand la relation est clairement du type « X est un Y » et que la sous-classe partage vraiment l'essentiel du comportement du parent. Si tu tires sur l'héritage juste pour mutualiser une ou deux méthodes utilitaires, passe plutôt par la composition — donne à la classe un champ qui contient l'objet utilitaire :

index.js
Output
Click Run to see the output here.

Les arbres d'héritage profonds (Animal -> Mammal -> Dog -> WorkingDog -> PoliceDog) rendent super bien sur un diagramme, mais deviennent vite un cauchemar dans le code : une modification près de la racine se propage de façon imprévisible à travers tous les descendants. La plupart des bases de code saines restent à un ou deux niveaux de profondeur et s'appuient sur la composition pour le reste.

La suite : les membres statiques

Tout ce qui est présenté dans ce document vit sur les instances — des méthodes que l'on appelle via new Thing().something(). Parfois, on a besoin de méthodes ou de données qui appartiennent à la classe elle-même, et non à une instance en particulier. C'est exactement le rôle de static, et c'est ce qu'on va voir maintenant.

Questions fréquentes

Comment fonctionne l'héritage en JavaScript ?

Une classe peut hériter d'une autre via extends. La sous-classe récupère l'ensemble des méthodes et champs du parent, et peut en ajouter ou en redéfinir. En coulisses, JavaScript relie le prototype de la sous-classe à celui du parent : la recherche de méthode remonte donc automatiquement la chaîne.

À quoi sert super en JavaScript ?

super(...) appelle le constructeur de la classe parente — et il faut impérativement l'appeler avant d'utiliser this dans le constructeur d'une sous-classe. super.methode(...), lui, invoque la version parente d'une méthode : c'est la façon d'étendre un comportement au lieu de le remplacer complètement.

Faut-il choisir l'héritage ou la composition en JavaScript ?

L'héritage a du sens quand il y a une vraie relation « est un » et que la sous-classe partage l'essentiel du comportement du parent. Dès qu'il s'agit juste de réutiliser du code, mieux vaut passer par la composition — des objets qui en contiennent d'autres. Les hiérarchies de classes profondes vieillissent mal ; dans la vraie vie, on dépasse rarement un ou deux niveaux.

Apprendre à coder avec Coddy

COMMENCER