Sorunuzda gösterdiğiniz her iki kod örneği de prototip kalıtımdan yararlanır. Aslında JavaScript'te yazdığınız herhangi bir nesne yönelimli kod, prototip kalıtımın bir paradigmasıdır. JavaScript'in klasik kalıtımı yoktur. Bu işleri biraz düzeltmeli:
Inheritance
|
+-----------------------------+
| |
v v
Prototypal Classical
|
+------------------------------+
| |
v v
Prototypal Pattern Constructor Pattern
Gördüğünüz gibi prototip kalıtım ve klasik kalıtım, iki farklı kalıtım paradigmasıdır. Self, Lua ve JavaScript gibi bazı diller prototip kalıtımı destekler. Ancak C ++, Java ve C # gibi çoğu dil klasik kalıtımı destekler.
Nesne Tabanlı Programlamaya Hızlı Bir Bakış
Hem prototip kalıtım hem de klasik kalıtım, nesne yönelimli programlama paradigmalarıdır (yani nesnelerle ilgilenirler). Nesneler, gerçek dünya varlığının özelliklerini kapsayan basit soyutlamalardır (yani, programdaki gerçek sözcükleri temsil ederler). Bu soyutlama olarak bilinir.
Soyutlama: Bilgisayar programlarında gerçek dünyadaki şeylerin temsili.
Teorik olarak bir soyutlama, "belirli örneklerden ortak özelliklerin çıkarılmasıyla oluşturulan genel bir kavram" olarak tanımlanır. Ancak bu açıklama uğruna bunun yerine yukarıda belirtilen tanımı kullanacağız.
Şimdi bazı nesnelerin birçok ortak noktası var. Örneğin bir çamur bisikleti ve bir Harley Davidson birçok ortak noktaya sahiptir.
Çamur bisikleti:
Bir Harley Davidson:
Çamur bisikleti ve Harley Davidson ikisi de bisiklet. Dolayısıyla bisiklet, hem çamur bisikletinin hem de Harley Davidson'un bir genellemesidir.
Bike
|
+---------------------------------+
| |
v v
Mud Bike Harley Davidson
Yukarıdaki örnekte bisiklet, çamur bisikleti ve Harley Davidson hepsi soyutlamalardır. Ancak bisiklet, çamur bisikletinin ve Harley Davidson'un daha genel bir soyutlamasıdır (yani hem çamur bisikleti hem de Harley Davidson belirli bisiklet türleridir).
Genelleme: Daha spesifik bir soyutlamanın bir soyutlaması.
Nesne yönelimli programlamada nesneler yaratırız (gerçek dünya varlıklarının soyutlamalarıdır) ve bu nesnelerin genellemelerini oluşturmak için sınıfları veya prototipleri kullanırız. Genellemeler miras yoluyla oluşturulur. Bisiklet, çamur bisikletinin bir genellemesidir. Bu nedenle çamur bisikletleri bisikletlerden miras alınır.
Klasik Nesne Tabanlı Programlama
Klasik nesne yönelimli programlamada iki tür soyutlamaya sahibiz: sınıflar ve nesneler. Daha önce belirtildiği gibi bir nesne, gerçek dünya varlığının bir soyutlamasıdır. Öte yandan bir sınıf, bir nesnenin veya başka bir sınıfın soyutlamasıdır (yani bir genellemedir). Örneğin şunları göz önünde bulundurun:
+----------------------+----------------+---------------------------------------+
| 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. |
+----------------------+----------------+---------------------------------------+
Klasik nesne yönelimli programlama dillerinde görebileceğiniz gibi nesneler yalnızca soyutlamalardır (yani tüm nesnelerin soyutlama düzeyi 1'dir) ve sınıflar yalnızca genellemedir (yani, tüm sınıfların 1'den büyük bir soyutlama düzeyi vardır).
Klasik nesne yönelimli programlama dillerindeki nesneler yalnızca sınıflar başlatılarak oluşturulabilir:
class Human {
// ...
}
class Man extends Human {
// ...
}
Man johnDoe = new Man();
Klasik nesne yönelimli programlama dillerinde özetle, nesneler gerçek dünya varlıklarının soyutlamalarıdır ve sınıflar genelleştirmelerdir (yani nesnelerin veya diğer sınıfların soyutlamaları).
Dolayısıyla, soyutlama düzeyi arttıkça varlıklar daha genel hale gelir ve soyutlama düzeyi azaldıkça varlıklar daha spesifik hale gelir. Bu anlamda, soyutlama seviyesi, daha spesifik varlıklardan daha genel varlıklara kadar değişen bir ölçeğe benzer.
Prototypal Nesne Tabanlı Programlama
Prototip nesne yönelimli programlama dilleri, klasik nesne yönelimli programlama dillerinden çok daha basittir, çünkü prototip nesne yönelimli programlamada yalnızca bir tür soyutlamaya sahibiz (yani nesneler). Örneğin şunları göz önünde bulundurun:
+----------------------+----------------+---------------------------------------+
| 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. |
+----------------------+----------------+---------------------------------------+
Prototip nesne yönelimli programlama dillerinde görebileceğiniz gibi nesneler, gerçek dünya varlıklarının (bu durumda basitçe nesne olarak adlandırılır) veya diğer nesnelerin (bu durumda soyutladıkları nesnelerin prototipleri olarak adlandırılırlar) soyutlamalarıdır. Dolayısıyla bir prototip bir genellemedir.
Prototip nesne yönelimli programlama dillerindeki nesneler, ya ex-nihilo (yani yoktan) ya da başka bir nesneden (yeni oluşturulan nesnenin prototipi haline gelir) oluşturulabilir:
var human = {};
var man = Object.create(human);
var johnDoe = Object.create(man);
Benim mütevazı görüşüme göre prototip nesne yönelimli programlama dilleri, klasik nesne yönelimli programlama dillerinden daha güçlüdür çünkü:
- Yalnızca bir tür soyutlama vardır.
- Genellemeler basit nesnelerdir.
Şimdiye kadar klasik kalıtım ile prototip kalıtım arasındaki farkı anlamış olmalısınız. Klasik miras, diğer sınıflardan miras alan sınıflarla sınırlıdır. Bununla birlikte, prototip kalıtımı yalnızca diğer prototiplerden miras alınan prototipleri değil, aynı zamanda prototiplerden miras alan nesneleri de içerir.
Prototip Sınıfı İzomorfizm
Prototiplerin ve sınıfların çok benzer olduğunu fark etmiş olmalısınız. Bu doğru. Onlar. Aslında o kadar benzerler ki, sınıfları modellemek için prototipleri gerçekten kullanabilirsiniz:
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;
}
}
Yukarıdaki CLASS
işlevi kullanarak, sınıflara benzeyen prototipler oluşturabilirsiniz:
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));
Ancak bunun tersi doğru değildir (yani, prototipleri modellemek için sınıfları kullanamazsınız). Bunun nedeni, prototiplerin nesne olması, ancak sınıfların nesne olmamasıdır. Bunlar tamamen farklı bir soyutlama türüdür.
Sonuç
Özetle, bir soyutlamanın "belirli örneklerden ortak özelliklerin çıkarılmasıyla oluşturulan genel bir kavram" olduğunu ve genellemenin "daha spesifik bir soyutlamanın soyutlaması" olduğunu öğrendik . Ayrıca prototip ve klasik kalıtım arasındaki farkları ve her ikisinin de aynı madalyonun iki yüzü olduğunu öğrendik.
Ayrılık notunda, iki prototip kalıtım modeli olduğunu belirtmek isterim: prototip kalıbı ve yapıcı modeli. Prototip model, prototip kalıtımın kanonik modelidir, oysa yapıcı modeli, prototip kalıtımın daha çok klasik kalıtım gibi görünmesini sağlamak için kullanılır. Şahsen ben prototip kalıbı tercih ederim.
Not: " Prototypal Kalıtım Neden Önemlidir " adlı blog yazısını yazan ve " Prototip kalıtımın klasiklere göre faydaları? " Sorusunu yanıtlayan kişiyim . Cevabım kabul edilen cevaptır.