2013-10-28 33 views
76

Ich habe so viele Links googled und kann keine gute Idee über den Unterschied zwischen klassischen Vererbung und prototypische Vererbung bekommen?klassische Vererbung vs prototypische Vererbung in Javascript

Ich habe einige Dinge aus diesen gelernt, aber ich bin immer noch verwirrt über die Konzepte.

Klassisches Erbe

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

klassisches Erbe Hat innerhalb prototypal Vererbung?

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

Von oben Link habe ich gelernt, wir zur Laufzeit in der klassischen Vererbungs nicht fügen Sie neue Methoden können. Ist das richtig? Aber Sie können den obigen Code überprüfen Ich kann "move" -Methode und alle Methoden zur Laufzeit durch Prototyp hinzufügen. Also ist das eine prototypbasierte klassische Vererbung? Wenn ja, was ist eigentlich klassische Vererbung und Prototypvererbung? Ich bin darüber verwirrt.

Prototypische Vererbung.

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

Ist das ähnlich zur klassischen Vererbung? Ich bin völlig verwirrt darüber, was prototypische Vererbung ist? Was ist klassische Vererbung? Warum ist klassische Vererbung schlecht?

Können Sie mir ein einfaches Beispiel geben, um diese auf einfache Weise besser zu verstehen.

Danke,

Siva

+0

Duplizieren , überprüfen Sie dies: http://StackOverflow.com/Questions/1595611/how-to-properly-create-a-Custom-Object-in-Javascript/1598077#1598077 –

+4

nicht sicher, was Sie hier sind - die erster Block des Codes _ist_ prototypische Vererbung, nicht klassisch. Ihr zweiter Codeblock hat überhaupt keine Vererbung! – Alnitak

+0

Dies kann xplain: http://blog.stephenwyattbush.com/2012/05/01/comparing-prototypal-and-classical-erbitance – HasanAboShally

Antwort

180

Sowohl die Code-Beispiele, die Sie in Ihrer Frage Verwendung von prototypische Vererbung machen demonstriert. Tatsächlich ist jeder objektorientierte Code, den Sie in JavaScript schreiben, ein Paradigma der prototypischen Vererbung. JavaScript hat einfach keine klassische Vererbung. Dies sollte die Dinge klären ein bisschen:

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

Wie Sie prototypal Erbe und klassische Erbe sind zwei verschiedene Paradigmen der Vererbung zu sehen. Einige Sprachen wie Self, Lua und JavaScript unterstützen die prototypische Vererbung. Die meisten Sprachen wie C++, Java und C# unterstützen jedoch die klassische Vererbung.


Eine Kurzübersicht der Objektorientierte Programmierung

Both prototypal Vererbung und klassischer Erbe sind objektorientierte Programmierparadigmen (das heißt sie mit Objekten zu tun). Objekte sind einfach Abstraktionen, die die Eigenschaften einer realen Entität kapseln (d. H. Sie repräsentieren reale Wortsachen im Programm). Dies wird als Abstraktion bezeichnet.

Abstraktion: Die Darstellung von realen Dingen in Computerprogrammen.

Theoretisch ist eine Abstraktion definiert als "ein allgemeines Konzept, das durch Extrahieren gemeinsamer Merkmale aus bestimmten Beispielen gebildet wird". Für diese Erklärung verwenden wir stattdessen die oben genannte Definition.

Nun haben einige Objekte viele Gemeinsamkeiten. Zum Beispiel haben ein Schlammrad und eine Harley Davidson viel gemeinsam.

Ein Schlamm Fahrrad:

A mud bike.

A Harley Davidson:

A Harley Davidson

Ein Schlamm Fahrrad und eine Harley Davidson sind beide Fahrräder. Daher ist ein Fahrrad eine Verallgemeinerung sowohl eines Schlammfahrrads als auch einer Harley Davidson.

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

Im obigen Beispiel sind das Fahrrad, das Schlammrad und die Harley Davidson Abstraktionen. Jedoch ist das Fahrrad eine allgemeinere Abstraktion des Schlammfahrrads und der Harley Davidson (d. H. Sowohl das Schlammrad als auch die Harley Davidson sind spezifische Arten von Fahrrädern).

Verallgemeinerung: Eine Abstraktion einer spezifischeren Abstraktion.

In der objektorientierten Programmierung erstellen wir Objekte (die Abstraktionen von Entitäten aus der realen Welt sind) und verwenden entweder Klassen oder Prototypen, um Verallgemeinerungen dieser Objekte zu erzeugen. Verallgemeinerungen werden über Vererbung erstellt. Ein Fahrrad ist eine Verallgemeinerung eines Schlammfahrrades. Daher erben Mud Bikes von Fahrrädern.


Klassische Objektorientierte Programmierung

In der klassischen objektorientierten Programmierung haben wir zwei Arten von Abstraktionen: Klassen und Objekte. Ein Objekt ist, wie bereits erwähnt, eine Abstraktion einer realen Welteinheit. Eine Klasse auf der anderen Seite ist eine Abstraktion eines Objekts oder einer anderen Klasse (d. H. Es ist eine Verallgemeinerung). Betrachten wir zum Beispiel:

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

Wie Sie in der klassischen objektorientierten Programmiersprachen sehen können Objekte nur Abstraktionen sind (dh alle Objekte haben eine Abstraktionsebene von 1) und Klassen sind nur Verallgemeinerungen (dh alle Klassen haben eine Abstraktion Stufe größer als 1).

Objekte in der klassischen objektorientierten Programmiersprachen kann nur durch Instanziieren Klassen erstellt werden:

class Human { 
    // ... 
} 

class Man extends Human { 
    // ... 
} 

Man johnDoe = new Man(); 

In der Summierung in der klassischen objektorientierten Programmiersprachen Objekte Abstraktionen der realen Welt Entitäten und Klassen sind Verallgemeinerungen (dh Abstraktionen von entweder Objekten oder anderen Klassen).

Mit der Ebene der Abstraktion werden die Entitäten allgemeiner und mit abnehmender Abstraktionsebene werden die Entitäten spezifischer. In diesem Sinne ist die Abstraktionsebene analog zu einer Skala, die von spezifischeren Entitäten zu allgemeineren Entitäten reicht.


Prototypische Objektorientierte Programmierung

Prototypische objektorientierten Programmiersprachen sind viel einfacher als die klassischen objektorientierten Programmiersprachen, weil in prototypal objektorientierten Programmierung nur wir eine Art von Abstraktion (dh Objekte) . Betrachten wir zum Beispiel:

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

Wie Sie in prototypal objektorientierten Programmiersprachen Objekte sind Abstraktionen von entweder realen Welt Entitäten (in diesem Fall werden sie einfach als Objekte bezeichnet) oder andere Objekte (in diesem Fall werden sie sehen können, sind genannt Prototypen der Objekte, die sie abstrahieren). Daher ist ein Prototyp eine Verallgemeinerung.

Objekte in prototypal objektorientierten Programmiersprachen erstellt werden können, entweder ex-nihilo (dh aus dem Nichts) oder von einem anderen Objekt (das ist der Prototyp des neu erstellten Objekts wird):

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

In meinem bescheidene Meinung prototypische objektorientierte Programmiersprachen sind leistungsfähiger als klassische objektorientierte Programmiersprachen, weil:

  • Es gibt nur eine Art der Abstraktion.
  • Verallgemeinerungen sind einfach Objekte.
  • Inzwischen müssen Sie den Unterschied zwischen klassischer Vererbung und prototypischer Vererbung erkannt haben. Klassische Vererbung ist auf Klassen beschränkt, die von anderen Klassen erben. Die prototypische Vererbung umfasst jedoch nicht nur Prototypen, die von anderen Prototypen stammen, sondern auch Objekte, die von Prototypen stammen.


    Prototype-Klasse Isomorphie

    Sie haben müssen bemerkt, dass Prototypen und Klassen sehr ähnlich sind. Das ist richtig. Sie sind. In der Tat sind sie so ähnlich, dass man tatsächlich Prototypen Klassen modellieren verwenden können:

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

    Unter Verwendung der oben CLASS Funktion können Sie Prototypen erstellen können, wie Klassen aussehen:

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

    Das Gegenteil ist jedoch nicht wahr (dh Sie können keine Klassen verwenden, um Prototypen zu modellieren). Dies liegt daran, dass Prototypen Objekte sind, aber Klassen keine Objekte sind. Sie sind eine ganz andere Art der Abstraktion.


    Fazit

    In Summe haben wir gelernt, dass eine Abstraktion ein „ein allgemeines Konzept durch Extrahieren gemeinsame Merkmale von spezifischen Beispielen gebildet“ und Verallgemeinerung ist „eine Abstraktion einer spezifischeren Abstraktion“ ist.Wir haben auch von den Unterschieden zwischen prototypischer und klassischer Vererbung erfahren und wie sie beide zwei Gesichter derselben Medaille sind.

    Auf einer Abschiedsnotiz möchte ich bemerken, dass es zwei Muster der prototypischen Vererbung gibt: das prototypische Muster und das Konstruktormuster. Das prototypische Muster ist das kanonische Muster der prototypischen Vererbung, während das Konstruktormuster verwendet wird, um die prototypische Vererbung eher wie eine klassische Vererbung aussehen zu lassen. Persönlich bevorzuge ich das prototypische Muster.

    P.S. Ich bin der Typ, der den Blogpost "Why Prototypal Inheritance Matters" geschrieben und die Frage "Benefits of prototypal inheritance over classical?" beantwortet hat. Meine Antwort ist die angenommene Antwort.

    +1

    Vielen Dank für Ihre wunderbare Antwort. Ich muss verstehen, wie Prototypmuster besser mit Konstruktormuster verglichen werden können. – SivaRajini

    +1

    Ich habe eine vergleichende Kritik über Konstruktoren vs Prototypen in meinem Blog geschrieben: http://aaditmshah.github.io/why-prototypal-inheritance-matters/#constructors_vs_prototypes –

    +0

    Also, wäre es richtig zu sagen, dass wenn wir Funktionen verwenden in Javascript, um Vererbung zu erreichen, verwenden wir ein wenig das klassische Vererbungsmodell und wenn wir einfache Objekte verwenden, prototypische Vererbung (beide intern nach prototypischen Vererbung)? – Swanidhi

    1

    Vor der Erbschaft springt, werden wir einen Blick auf zwei primären Modelle nehmen Instanzen (Objekte) in Javascript zu erstellen:

    klassisches Modell: Objekt wird aus einem Plan (Klasse) erstellt

    class Person { 
        fn() {...} 
    } // or constructor function say, function Person() {} 
    
    // create instance 
    let person = new Person(); 
    

    Prototypmodell: Objekt wird direkt von einem anderen Objekt erstellt.

    // base object 
    let Person = { fn(){...} } 
    
    // instance 
    let person = Object.create(Person); 
    

    In beiden Fällen wird die Vererbung * durch Verknüpfen von Objekten mithilfe eines Prototypobjekts erreicht.

    (* Basisklasse Methoden sind über. Abgeleiteten Klasse durch das Prototypobjekt und nicht explizit in abgeleiteten Klasse vorhanden sein erforderlich.)

    Hier ist eine gute Erklärung ist besser zu verstehen (http://www.objectplayground.com/)