web-dev-qa-db-fra.com

héritage classique vs héritage prototypique en javascript

J'ai cherché tant de liens sur Google et je ne peux pas me faire une bonne idée de la différence entre l'héritage classique et l'héritage prototypique?

J'ai appris certaines choses mais je ne comprends toujours pas les concepts.

Héritage classique

// Shape - superclass
function Shape() {
  this.x = 0;
  this.y = 0;
}

//superclass method
Shape.prototype.move = function(x, y) {
    this.x += x;
    this.y += y;
    console.info("Shape moved.");
};

// Rectangle - subclass
function Rectangle() {
  Shape.call(this); //call super constructor.
}

//subclass extends superclass
Rectangle.prototype = Object.create(Shape.prototype);

L'héritage classique utilise-t-il l'héritage prototypique à l'intérieur?

http://aaditmshah.github.io/why-prototypal-inheritance-matters/

À partir du lien ci-dessus, j'ai appris que nous ne pouvons pas ajouter de nouvelles méthodes au moment de l'exécution en héritage classique . Est-ce correct? Mais vous pouvez vérifier le code ci-dessus . Je peux ajouter la méthode "move" et toutes les méthodes au moment de l'exécution via le prototype . Donc, ceci est un héritage classique basé sur un prototype? Si tel est le cas, quel est l'héritage classique réel et l'héritage prototype? Je suis confus à ce sujet.

Héritage prototype.

function Circle(radius) {
    this.radius = radius;
}
Circle.prototype.area = function () {
    var radius = this.radius;
    return Math.PI * radius * radius;
};
Circle.prototype.circumference: function () {
    return 2 * Math.PI * this.radius;
};
var circle = new Circle(5);
var circle2 = new Circle(10);

Est-ce similaire à l'héritage classique? Je suis totalement confus sur ce qu'est l'héritage prototypique? Qu'est-ce que l'héritage classique? Pourquoi l'héritage classique est-il mauvais?

Pouvez-vous me donner un exemple simple pour une meilleure compréhension de ceux-ci d'une manière simple.

Merci,

Shiva

108
SivaRajini

Les exemples de code que vous avez présentés dans votre question utilisent tous deux 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 éclaircir un peu les choses:

                                   Inheritance
                                        |
                         +-----------------------------+
                         |                             |
                         v                             v
                    Prototypal                     Classical
                         |
         +------------------------------+
         |                              |
         v                              v
Prototypal Pattern             Constructor Pattern

Comme vous pouvez le constater, l'héritage prototype et l'héritage classique sont deux paradigmes différents de l'héritage. Certaines langues telles que 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 prototype et l'héritage classique sont tous deux 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 éléments Word réels dans le programme). Ceci est connu comme l'abstraction.

Abstraction: Représentation de choses du monde réel dans des programmes informatiques.

Théoriquement, une abstraction est définie comme "un concept général formé par l'extraction de caractéristiques communes à partir d'exemples spécifiques". Cependant, pour les besoins de cette explication, nous allons utiliser la définition susmentionnée à 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:

A mud bike.

A Harley Davidson:

A Harley Davidson

Un vélo de boue et une Harley Davidson sont les deux vélos. Par conséquent, un vélo est une généralisation d'un vélo de boue et d'un Harley Davidson.

                   Bike
                     |
    +---------------------------------+
    |                                 |
    v                                 v
Mud Bike                       Harley Davidson

Dans l'exemple ci-dessus, le vélo, le vélo de boue et le Harley Davidson sont tous des abstractions. Cependant, le vélo est une abstraction plus générale du vélo de boue et du Harley Davidson (c’est-à-dire que le vélo de boue et le Harley Davidson sont des types spécifiques de vélos).

Généralisation: 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 via l'héritage. Un vélo est une généralisation d'un vélo de boue. D'où les vélos de boue hérités des vélos.


Programmation Classique Orientée Objet

En programmation orientée objet classique, nous avons deux types d'abstractions: les classes et les objets. Comme mentionné précédemment, un objet 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érons:

+----------------------+----------------+---------------------------------------+
| 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 constater dans les langages de programmation orientés objet classiques, les objets ne sont que des abstractions (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 Prototypale Orientée Objet

Les langages de programmation prototypiques orientés objet sont beaucoup plus simples que les langages de programmation orientés objet classiques car dans la programmation prototypique orientée objet, nous n’avons qu’un seul type d’abstraction (c’est-à-dire les objets). Par exemple, considérons:

+----------------------+----------------+---------------------------------------+
| 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 constater dans les langages de programmation orientés objet prototypés, les objets sont des abstractions d'entités du monde réel (dans ce cas, elles sont simplement appelées objets) ou d'autres objets (auquel cas, elles sont appelées des prototypes de ces objets). Un prototype est donc une généralisation.

Les objets dans les langages de programmation orientés objet prototypiques peuvent être créés soit ex-nihilo (c'est-à-dire sans 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);

A mon humble avis, les langages de programmation orientés objet prototypes sont plus puissants que les langages de programmation orientés objet classiques pour les raisons suivantes:

  1. Il n'y a qu'un seul type d'abstraction.
  2. Les généralisations sont simplement des objets.

A présent, vous devez avoir compris la différence entre héritage classique et héritage prototype. L'héritage classique est limité aux classes héritant d'autres classes. Cependant, l'héritage de prototypes comprend non seulement des prototypes héritant d'autres prototypes, mais également des objets héritant de 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 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 fonction CLASS ci-dessus, vous pouvez créer des prototypes ressemblant à 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 toutefois 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. Ils sont un type d'abstraction totalement différent.


Conclusion

En résumé, nous avons appris qu'une abstraction est un "un concept général formé par l'extraction de caractéristiques communes à partir d'exemples spécifiques" et que la généralisation est "une abstraction d'une abstraction plus spécifique". Nous avons également découvert les différences entre héritage classique et prototypique et expliqué comment les deux sont les deux faces d’une même pièce.

Sur une note de séparation, j'aimerais faire remarquer qu'il existe deux modèles d'héritage prototypique: le modèle prototypal et le modèle constructeur. Le modèle prototypal est le modèle canonique de l'héritage prototypal, tandis que le modèle constructeur est utilisé pour que l'héritage prototypal ressemble davantage à l'héritage classique. Personnellement, je préfère le motif prototypal.

P.S. Je suis le gars qui a écrit l'article " Pourquoi l'héritage prototypal est-il important " et a-t-il répondu à la question " Les avantages de l'héritage prototypique par rapport à la méthode classique? ". Ma réponse est la réponse acceptée.

231
Aadit M Shah

Avant de nous lancer dans l'héritage, nous allons examiner deux modèles primaires pour créer des instances (objets) en javascript:

Modèle classique: L'objet est créé à partir d'un plan (classe)

class Person {
  fn() {...}
} // or constructor function say, function Person() {}

// create instance
let person = new Person();

Modèle prototype: L'objet est créé directement à partir d'un autre objet.

// base object
let Person = { fn(){...} }

// instance
let person = Object.create(Person);

Dans les deux cas, l'héritage * est obtenu en liant des objets à l'aide d'un objet prototype.

(* Les méthodes de classe de base sont accessibles via. classe dérivée via l'objet prototype et n'ont pas besoin d'être explicitement présentes dans la classe dérivée.)

Voici une bonne explication pour mieux comprendre ( http://www.objectplayground.com/ )

6
everlasto