Comment organiser votre code orienté objet avec l’héritage
Il est courant de réutiliser du code dans la programmation orientée objet. Les classes existent pour que vous puissiez créer des objets sans avoir à écrire les mêmes variables et fonctions encore et encore.
Mais qu'en est-il des classes elles-mêmes? Parfois, les classes sont également très similaires. Par exemple, un arbre a des branches, des racines et un tronc. Cela s'applique aux Elms, Oaks et Ponderosa Pines.
Si vous ajoutiez un arbre à un jeu, vous pourriez créer des parties d'arbre pour des dizaines d'arbres. Mais il serait plus facile de créer une classe d'arbre et de faire en sorte que chaque autre arbre hérite de ses propriétés.
Pourquoi l'héritage est-il important?
Il existe un concept dans la programmation orientée objet appelé «garder au sec». DRY signifie "Don't Repeat Yourself". Si vous vous surprenez à copier et coller beaucoup de code, vous faites également de la place pour de nombreuses erreurs.
Disons que vous écrivez le code d'un nouveau jeu Tamagotchi. Le premier animal de compagnie virtuel sera un ours polaire. Vous créez donc une classe appelée PolarBear dans JavaScript / TypeScript.
class PolarBear {
private _weight: number = 990;
constructor(weight: number = 0) {
this._weight = weight
}
makeNoise() {
console.log("made a roar");
}
eat() {
console.log("eats whatever it wants");
}
sleep() {
console.log("got a good night's sleep");
}
roam() {
console.log("wandered about aimlessly");
}
}
Ensuite, votre patron vous dit que la haute direction a fait une énorme percée. Ils ont réalisé que ce n'était plus les années 90 et qu'ils pouvaient contenir plus de 5K de mémoire dans le Tamagotchi. Et maintenant, ils veulent tous les ours.
Vous retroussez vos manches et retournez au travail, créant des copies de la classe des ours. Ensuite, votre patron frappe à nouveau à votre porte. Il s'avère qu'ils veulent que le jeu soit plus éducatif. Vous devez maintenant ajouter des informations d'origine à chaque animal.
Vous ne dupliquez plus de code. Vous modifiez maintenant des centaines de lignes de code pour les huit espèces d'ours. C'est ainsi que les erreurs se produisent et que les bogues sont introduits.
Alors que vous vous éloignez, votre patron revient à nouveau. Désormais, la haute direction veut également tous les rongeurs du jeu. Oh, et une girafe.
Vous savez que lorsque vous aurez terminé, ils voudront aussi des singes ou autre chose. Il doit y avoir un meilleur moyen.
Au lieu de créer des Tamogatchi de nouvelle génération, vous pouvez toujours jouer avec ceux qui existent déjà .
Héritage à la rescousse

Afin d'apprivoiser votre ménagerie virtuelle, vous allez devoir vous organiser. L'héritage vous aide à organiser vos classes en y ajoutant des relations parent et enfant.
Les ours noirs, les grizzlis et les ours paresseux sont tous des ours. Les ours, les rongeurs et les singes sont tous des animaux. Et c'est ainsi que nous allons structurer notre arbre généalogique.

Voici à quoi ressemble une partie du code:
class Animal {
private _weight: number;
private _origin: string;
constructor(weight: number = 0, origin: string = "") {
this._weight = weight;
this._origin = origin;
}
makeNoise(noise: string = "") {
console.log("made a noise that sounded like: " + noise);
}
eat(food: string = "") {
console.log("eats " + food);
}
sleep() {
console.log("got a good night's sleep");
}
roam() {
console.log("wandered about aimlessly");
}
}
class Bear extends Animal {
constructor(weight: number, origin: string) {
super(weight, origin);
}
makeNoise(noise: string = "roar") {
super.makeNoise(noise);
}
eat(food: string = "whatever it wants") {
super.eat(food);
}
}
class GrizzlyBear extends Bear {
constructor(weight: number = 600, origin: string = "North America") {
super(weight, origin);
}
}
class Panda extends Bear {
constructor(weight: number = 230, origin: string = "China") {
super(weight, origin);
}
makeNoise() {
super.makeNoise("squeek");
}
eat() {
super.eat("shoots and leaves");
}
}
Vous pouvez jouer avec le code dans le bac à sable TypeScript .
C'était un gros échantillon, mais le code est assez simple et toutes les classes descendent de la classe Animal . Vous pouvez voir que Bear étend Animal . Et GrizzlyBear et Panda étendent la classe Bear . La classe Bear crée des fonctions de son et de consommation par défaut. La classe GrizzlyBear utilise ces fonctions par défaut, mais pas le Panda .
En d'autres termes, la classe GrizzlyBear ne remplace pas les fonctions Bear . Puisque GrizzlyBear étend Bear , il utilisera automatiquement les fonctions définies par Bear . Mais puisque Panda remplace les fonctions makeNoise et eat , il les utilisera à la place.
Trouver des relations avec la technique "is-a, has-a"
Pour déterminer si une classe devrait vraiment étendre une autre classe, vous pouvez vous demander s'il existe une relation «est-a» ou «a-a» entre elles.
- Un lémurien "est-un" singe.
- Un kangourou "est" un marsupial.
- Une patte de lapin n'est cependant pas un lapin. Un lapin a une patte.
Cet exemple est un peu simpliste, mais lorsqu'il s'agit de classes du monde réel, il peut être très utile.
Pratique et compréhension pratiques de l'héritage

Prêt à appliquer ce que vous avez appris?
- Visitez le bac à sable et remplissez le reste des classes d'animaux de l'exemple ci-dessus.
- Ajoutez une classe Monkey .
- Ajoutez une classe ProboscisMonkey qui étend votre classe de singe.
L'héritage est plus qu'un simple code bien organisé. C'est un élément central de la programmation orientée objet. L'héritage permet de rationaliser la communication entre les objets. Et cela permet une conception orientée objet plus avancée, comme avec le polymorphisme. Vous pouvez en savoir plus sur l'héritage dans la documentation TypeScript .