Les deux exemples de code que vous avez présentés dans votre question utilisent l'héritage prototypique. En fait, tout code orienté objet que vous écrivez en JavaScript est un paradigme d'héritage prototypique. JavaScript n'a tout simplement pas d'héritage classique. Cela devrait clarifier un peu les choses:
Inheritance
|
+-----------------------------+
| |
v v
Prototypal Classical
|
+------------------------------+
| |
v v
Prototypal Pattern Constructor Pattern
Comme vous pouvez le voir, l'héritage prototypique et l'héritage classique sont deux paradigmes différents d'héritage. Certains langages comme Self, Lua et JavaScript prennent en charge l'héritage prototypique. Cependant, la plupart des langages comme C ++, Java et C # prennent en charge l'héritage classique.
Un aperçu rapide de la programmation orientée objet
L'héritage prototypique et l'héritage classique sont des paradigmes de programmation orientés objet (c'est-à-dire qu'ils traitent d'objets). Les objets sont simplement des abstractions qui encapsulent les propriétés d'une entité du monde réel (c'est-à-dire qu'ils représentent des mots réels dans le programme). C'est ce qu'on appelle l'abstraction.
Abstraction: représentation d'objets du monde réel dans des programmes informatiques.
Théoriquement, une abstraction est définie comme "un concept général formé en extrayant des caractéristiques communes à partir d'exemples spécifiques". Cependant, pour cette explication, nous allons utiliser la définition ci-dessus à la place.
Maintenant, certains objets ont beaucoup de choses en commun. Par exemple, un vélo de boue et une Harley Davidson ont beaucoup en commun.
Un vélo de boue:
Une Harley Davidson:
Un vélo de boue et une Harley Davidson sont tous deux des vélos. Par conséquent, un vélo est une généralisation à la fois d'un vélo de boue et d'une Harley Davidson.
Bike
|
+---------------------------------+
| |
v v
Mud Bike Harley Davidson
Dans l'exemple ci-dessus, la moto, la moto de boue et la Harley Davidson sont toutes des abstractions. Cependant, le vélo est une abstraction plus générale du vélo de boue et de la Harley Davidson (c'est-à-dire que le vélo de boue et la Harley Davidson sont des types de vélos spécifiques).
Généralisation: une abstraction d'une abstraction plus spécifique.
Dans la programmation orientée objet, nous créons des objets (qui sont des abstractions d'entités du monde réel) et nous utilisons des classes ou des prototypes pour créer des généralisations de ces objets. Les généralisations sont créées par héritage. Un vélo est une généralisation d'un vélo de boue. C'est pourquoi les vélos de boue héritent des vélos.
Programmation classique orientée objet
Dans la programmation classique orientée objet, nous avons deux types d'abstractions: les classes et les objets. Un objet, comme mentionné précédemment, est une abstraction d'une entité du monde réel. Une classe par contre est une abstraction d'un objet ou d'une autre classe (c'est-à-dire une généralisation). Par exemple, considérez:
+----------------------+----------------+---------------------------------------+
| Level of Abstraction | Name of Entity | Comments |
+----------------------+----------------+---------------------------------------+
| 0 | John Doe | Real World Entity. |
| 1 | johnDoe | Variable holding object. |
| 2 | Man | Class of object johnDoe. |
| 3 | Human | Superclass of class Man. |
+----------------------+----------------+---------------------------------------+
Comme vous pouvez le voir dans les langages de programmation orientés objet classiques, les objets ne sont que des abstractions (c'est-à-dire que tous les objets ont un niveau d'abstraction de 1) et les classes ne sont que des généralisations (c'est-à-dire que toutes les classes ont un niveau d'abstraction supérieur à 1).
Les objets dans les langages de programmation orientés objet classiques ne peuvent être créés qu'en instanciant des classes:
class Human {
// ...
}
class Man extends Human {
// ...
}
Man johnDoe = new Man();
En résumé, dans les langages de programmation orientés objet classiques, les objets sont des abstractions d'entités du monde réel et les classes sont des généralisations (c'est-à-dire des abstractions d'objets ou d'autres classes).
Par conséquent, à mesure que le niveau d'abstraction augmente, les entités deviennent plus générales et à mesure que le niveau d'abstraction diminue, les entités deviennent plus spécifiques. En ce sens, le niveau d'abstraction est analogue à une échelle allant d'entités plus spécifiques à des entités plus générales.
Programmation orientée objet prototypique
Les langages de programmation orientés objet prototypiques sont beaucoup plus simples que les langages de programmation orientés objet classiques car dans la programmation orientée objet prototypique, nous n'avons qu'un seul type d'abstraction (c'est-à-dire les objets). Par exemple, considérez:
+----------------------+----------------+---------------------------------------+
| Level of Abstraction | Name of Entity | Comments |
+----------------------+----------------+---------------------------------------+
| 0 | John Doe | Real World Entity. |
| 1 | johnDoe | Variable holding object. |
| 2 | man | Prototype of object johnDoe. |
| 3 | human | Prototype of object man. |
+----------------------+----------------+---------------------------------------+
Comme vous pouvez le voir dans les langages de programmation orientés objet prototypiques, les objets sont des abstractions d'entités du monde réel (auquel cas ils sont simplement appelés objets) ou d'autres objets (dans ce cas, ils sont appelés prototypes des objets qu'ils abstraits). Un prototype est donc une généralisation.
Les objets dans les langages de programmation orientés objet prototypiques peuvent être créés ex-nihilo (c'est-à-dire à partir de rien) ou à partir d'un autre objet (qui devient le prototype de l'objet nouvellement créé):
var human = {};
var man = Object.create(human);
var johnDoe = Object.create(man);
À mon humble avis, les langages de programmation orientés objet prototypiques sont plus puissants que les langages de programmation orientés objet classiques car:
- Il n'y a qu'un seul type d'abstraction.
- Les généralisations ne sont que des objets.
Vous devez maintenant avoir réalisé la différence entre l'héritage classique et l'héritage prototypique. L'héritage classique est limité aux classes héritant d'autres classes. Cependant, l'héritage prototypique comprend non seulement les prototypes héritant d'autres prototypes, mais également les objets héritant des prototypes.
Isomorphisme de classe prototype
Vous devez avoir remarqué que les prototypes et les classes sont très similaires. C'est vrai. Elles sont. En fait, ils sont si similaires que vous pouvez réellement utiliser des prototypes pour modéliser des classes:
function CLASS(base, body) {
if (arguments.length < 2) body = base, base = Object.prototype;
var prototype = Object.create(base, {new: {value: create}});
return body.call(prototype, base), prototype;
function create() {
var self = Object.create(prototype);
return prototype.hasOwnProperty("constructor") &&
prototype.constructor.apply(self, arguments), self;
}
}
En utilisant la CLASS
fonction ci-dessus , vous pouvez créer des prototypes qui ressemblent à des classes:
var Human = CLASS(function () {
var milliseconds = 1
, seconds = 1000 * milliseconds
, minutes = 60 * seconds
, hours = 60 * minutes
, days = 24 * hours
, years = 365.2425 * days;
this.constructor = function (name, sex, dob) {
this.name = name;
this.sex = sex;
this.dob = dob;
};
this.age = function () {
return Math.floor((new Date - this.dob) / years);
};
});
var Man = CLASS(Human, function (Human) {
this.constructor = function (name, dob) {
Human.constructor.call(this, name, "male", dob);
if (this.age() < 18) throw new Error(name + " is a boy, not a man!");
};
});
var johnDoe = Man.new("John Doe", new Date(1970, 0, 1));
L'inverse n'est cependant pas vrai (c'est-à-dire que vous ne pouvez pas utiliser de classes pour modéliser des prototypes). En effet, les prototypes sont des objets mais les classes ne sont pas des objets. Il s'agit d'un type d'abstraction entièrement différent.
Conclusion
En résumé, nous avons appris qu'une abstraction est un «concept général formé en extrayant des caractéristiques communes d'exemples spécifiques» et que la généralisation est «une abstraction d'une abstraction plus spécifique» . Nous avons également appris les différences entre l'héritage prototypique et classique et comment les deux sont les deux faces d'une même pièce.
En guise de conclusion, je voudrais faire remarquer qu'il existe deux modèles d'héritage prototypique: le modèle prototypique et le modèle constructeur. Le modèle prototypique est le modèle canonique de l'héritage prototypique tandis que le modèle du constructeur est utilisé pour que l'héritage prototypique ressemble davantage à l'héritage classique. Personnellement, je préfère le modèle prototypique.
PS Je suis le type qui a écrit le billet de blog " Pourquoi l'héritage prototypique est important " et a répondu à la question " Avantages de l'héritage prototypique par rapport au classique? ". Ma réponse est la réponse acceptée.