2013-10-28 17 views
76

Ho cercato su Google così tanti link e non riesco a farmi un'idea della differenza tra ereditarietà classica e eredità prototipale?ereditarietà classica dell'ereditarietà prototipale in javascript

Ho imparato alcune cose da questi, ma sono ancora confuso sui concetti.

eredità classica

// 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); 

Vuol eredità classica utilizzare l'ereditarietà prototipale dentro?

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

Dall'alto collegamento, ho imparato non possiamo aggiungere nuovi metodi in fase di esecuzione in eredità classica. È corretto? Ma è possibile controllare il codice sopra Posso aggiungere il metodo "sposta" e tutti i metodi in fase di esecuzione tramite il prototipo. Quindi questa è un'ereditarietà classica basata sul prototipo? In tal caso, qual è l'ereditarietà classica e l'ereditarietà del prototipo? Sono confuso su questo.

Eredità prototipale.

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); 

È simile all'ereditarietà classica? Sono totalmente confuso su cos'è l'eredità prototipale? Cos'è l'ereditarietà classica? Perché l'ereditarietà classica è cattiva?

Potete darmi un semplice esempio per comprenderli meglio in un modo semplice.

Grazie,

Siva

+0

duplicati , guarda questo: http://stackoverflow.com/questions/1595611/how-to-properly-create-a-custom-object-in-javascript/1598077#1598077 –

+4

non sai di cosa stai parlando - il primo blocco di codice _is_ l'eredità prototipica, non classica. Il tuo secondo blocco di codice non ha alcuna eredità! – Alnitak

+0

Questo può xplain: http://blog.stephenwyattbush.com/2012/05/01/comparing-prototypal-and-classical-inheritance – HasanAboShally

risposta

180

Entrambi gli esempi di codice che si dimostrò nella sua interrogazione fare uso di ereditarietà prototipale. In effetti qualsiasi codice orientato agli oggetti che scrivi in ​​JavaScript è un paradigma dell'ereditarietà prototipale. JavaScript semplicemente non ha ereditarietà classica. Questo dovrebbe chiarire le cose un po ':

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

Come si può vedere l'ereditarietà prototipale e l'eredità classica sono due diversi paradigmi di ereditarietà. Alcuni linguaggi come Self, Lua e JavaScript supportano l'ereditarietà prototipale. Tuttavia la maggior parte delle lingue come C++, Java e C# supportano l'ereditarietà classica.


Una veloce Panoramica dei

Sia ereditarietà prototipale programmazione orientata agli oggetti e di eredità classica sono paradigmi di programmazione orientata agli oggetti (cioè hanno a che fare con gli oggetti). Gli oggetti sono semplicemente astrazioni che incapsulano le proprietà di un'entità del mondo reale (cioè rappresentano le parole reali nel programma). Questo è noto come astrazione.

Astrazione: La rappresentazione di cose del mondo reale nei programmi per computer.

In teoria un'astrazione viene definita come "un concetto generale formato estraendo caratteristiche comuni da esempi specifici". Tuttavia, per il gusto di questa spiegazione, utilizzeremo invece la definizione sopra menzionata.

Ora alcuni oggetti hanno molte cose in comune. Ad esempio una bici da fango e una Harley Davidson hanno molto in comune.

Una moto di fango:

A mud bike.

una Harley Davidson:

A Harley Davidson

Una moto fango e una Harley Davidson sono entrambe le moto. Quindi una bici è una generalizzazione sia di una moto da fango che di una Harley Davidson.

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

Nell'esempio precedente la bicicletta, la bici da fango e l'Harley Davidson sono tutte astrazioni. Tuttavia, la bici è un'astrazione più generale della moto da fango e della Harley Davidson (vale a dire sia la moto da fango che l'Harley Davidson sono tipi specifici di bici).

Generalizzazione: Un'astrazione di un'astrazione più specifica.

Nella programmazione orientata agli oggetti creiamo oggetti (che sono astrazioni di entità del mondo reale) e usiamo le classi oi prototipi per creare generalizzazioni di questi oggetti. Le generalizzazioni sono create tramite l'ereditarietà. Una bici è una generalizzazione di una bici da fango. Quindi le bici da fango ereditano dalle biciclette.


classica programmazione orientata agli oggetti

Nella programmazione orientata agli oggetti classica abbiamo due tipi di astrazioni: classi e oggetti. Un oggetto, come accennato prima, è un'astrazione di un'entità del mondo reale. D'altra parte, una classe è un'astrazione di un oggetto o di un'altra classe (cioè è una generalizzazione). Ad esempio, si consideri:

+----------------------+----------------+---------------------------------------+ 
| 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.    | 
+----------------------+----------------+---------------------------------------+ 

Come si può vedere nei linguaggi di programmazione orientati agli oggetti classici oggetti sono solo astrazioni (vale a dire tutti gli oggetti hanno un livello di astrazione di 1) e le classi sono solo generalizzazioni (vale a dire tutte le classi hanno un'astrazione livello superiore a 1).

oggetti nei linguaggi di programmazione orientati agli oggetti classici possono essere creati solo da Istanziare classi:

class Human { 
    // ... 
} 

class Man extends Human { 
    // ... 
} 

Man johnDoe = new Man(); 

In somma nei linguaggi di programmazione orientati agli oggetti classici oggetti sono astrazioni di entità del mondo reale e le classi sono generalizzazioni (cioè astrazioni di entrambi gli oggetti o altre classi).

Di conseguenza, quando il livello di astrazione aumenta, le entità diventano più generali e man mano che il livello di astrazione diminuisce, le entità diventano più specifiche. In questo senso il livello di astrazione è analogo a una scala che va da entità più specifiche a entità più generali.


prototipale Object-Oriented Programming

prototipale linguaggi di programmazione orientati agli oggetti sono molto più semplici di linguaggi di programmazione orientati agli oggetti classici, perché in programmazione orientata agli oggetti prototipale abbiamo un solo tipo di astrazione (cioè gli oggetti) . Ad esempio, si consideri:

+----------------------+----------------+---------------------------------------+ 
| 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.    | 
+----------------------+----------------+---------------------------------------+ 

Come si può vedere nei linguaggi prototipali programmazione orientata agli oggetti Gli oggetti sono astrazioni di un'entità del mondo reale (nel qual caso essi sono semplicemente chiamati oggetti) o altri oggetti (nel qual caso essi sono chiamati prototipi di quegli oggetti che astraggono). Quindi un prototipo è una generalizzazione.

oggetti nei linguaggi di programmazione orientati agli oggetti prototipali possono essere creati sia ex-nihilo (cioè dal nulla), o da un altro oggetto (che diventa il prototipo del nuovo oggetto creato):

var human = {}; 
var man = Object.create(human); 
var johnDoe = Object.create(man); 

Nella mia humble opinion prototypal linguaggi di programmazione orientati agli oggetti sono più potenti dei classici linguaggi di programmazione orientati agli oggetti perché:

  1. C'è un solo tipo di astrazione.
  2. Le generalizzazioni sono semplicemente oggetti.

Ormai è necessario aver compreso la differenza tra ereditarietà classica e eredità prototipale. L'ereditarietà classica è limitata alle classi che ereditano da altre classi. Tuttavia, l'ereditarietà prototipale include non solo i prototipi che ereditano da altri prototipi, ma anche oggetti che ereditano dai prototipi.


Prototype-Class Isomorfismo

Avrai notato che i prototipi e le classi sono molto simili. È vero. Loro sono. In realtà essi sono così simili che si può effettivamente utilizzare prototipi per modellare le classi:

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; 
    } 
} 

Utilizzando la funzione di cui sopra CLASS è possibile creare prototipi che assomigliano a classi:

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)); 

il contrario non è vero, però (cioè non puoi usare le classi per modellare i prototipi). Questo perché i prototipi sono oggetti ma le classi non sono oggetti. Sono un tipo completamente diverso di astrazione.


Conclusione

Riassumendo abbiamo appreso che un astrazione è un "un concetto generale formata da estrazione di caratteristiche comuni da esempi specifici" e che generalizzazione è "un'astrazione di un'astrazione più specifico".Abbiamo anche appreso le differenze tra l'ereditarietà prototipale e classica e in che modo entrambi sono due facce della stessa medaglia.

In una nota di separazione vorrei sottolineare che esistono due modelli di ereditarietà prototipale: il modello prototipo e il modello di costruzione. Il modello prototipo è il modello canonico dell'ereditarietà prototipale mentre il modello del costruttore viene utilizzato per rendere l'ereditarietà prototipale più simile all'ereditarietà classica. Personalmente preferisco il modello prototipo.

P.S. Sono il ragazzo che ha scritto il post sul blog "Why Prototypal Inheritance Matters" e ha risposto alla domanda "Benefits of prototypal inheritance over classical?". La mia risposta è la risposta accettata.

+1

grazie per la tua meravigliosa risposta. ho bisogno di capire come il modello prototipale è meglio confrontare con il modello di costruzione. Ad esempio? – SivaRajini

+1

Ho scritto una critica comparativa sui costruttori rispetto ai prototipi nel mio blog: http://aaditmshah.github.io/why-prototypal-inheritance-matters/#constructors_vs_prototypes –

+0

Quindi, sarebbe corretto dire che quando usiamo le funzioni in javascript per raggiungere l'ereditarietà, usiamo un po 'il modello di ereditarietà classica e quando usiamo oggetti semplici l'ereditarietà prototipica (entrambi seguendo internamente l'eredità prototipica)? – Swanidhi

1

Prima di saltare in eredità, ci sarà uno sguardo a due modelli primari per creare istanze (oggetti) in javascript:

Modello classico: oggetto viene creato da un progetto (classe)

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

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

Modello prototipo: L'oggetto viene creato direttamente da un altro oggetto.

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

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

In entrambi i casi, l'ereditarietà * si ottiene collegando oggetti utilizzando l'oggetto prototipo.

(* metodi della classe base sono accessibili via. Classe derivata attraverso l'oggetto prototipo e non è necessario essere esplicitamente presente in classe derivata.)

Ecco una buona spiegazione per capire meglio (http://www.objectplayground.com/)