Kedua contoh kode yang Anda tunjukkan dalam pertanyaan Anda menggunakan pewarisan prototipe. Faktanya, kode berorientasi objek apa pun yang Anda tulis di JavaScript adalah paradigma pewarisan prototipe. JavaScript tidak memiliki warisan klasik. Ini harus menjelaskan sedikit:
Inheritance
|
+-----------------------------+
| |
v v
Prototypal Classical
|
+------------------------------+
| |
v v
Prototypal Pattern Constructor Pattern
Seperti yang Anda lihat, pewarisan prototipe dan pewarisan klasik adalah dua paradigma pewarisan yang berbeda. Beberapa bahasa seperti Self, Lua dan JavaScript mendukung pewarisan prototipe. Namun kebanyakan bahasa seperti C ++, Java dan C # mendukung pewarisan klasik.
Tinjauan Singkat Pemrograman Berorientasi Objek
Baik pewarisan prototipe dan pewarisan klasik adalah paradigma pemrograman berorientasi objek (yaitu, mereka berurusan dengan objek). Objek hanyalah abstraksi yang merangkum properti dari entitas dunia nyata (yaitu mereka mewakili hal-hal nyata dalam program). Ini dikenal sebagai abstraksi.
Abstraksi: Representasi hal-hal dunia nyata dalam program komputer.
Secara teoritis abstraksi didefinisikan sebagai "konsep umum yang dibentuk dengan mengekstraksi fitur umum dari contoh tertentu". Namun demi penjelasan ini, kami akan menggunakan definisi yang disebutkan di atas.
Sekarang beberapa objek memiliki banyak kesamaan. Misalnya sepeda lumpur dan Harley Davidson memiliki banyak kesamaan.
Sepeda lumpur:
Harley Davidson:
Sepeda lumpur dan Harley Davidson keduanya adalah sepeda. Karenanya sepeda adalah generalisasi dari sepeda lumpur dan Harley Davidson.
Bike
|
+---------------------------------+
| |
v v
Mud Bike Harley Davidson
Dalam contoh di atas, sepeda, sepeda lumpur, dan Harley Davidson, semuanya adalah abstraksi. Namun sepeda motor adalah abstraksi yang lebih umum dari sepeda lumpur dan Harley Davidson (yaitu sepeda lumpur dan Harley Davidson adalah jenis sepeda tertentu).
Generalisasi: Abstraksi dari abstraksi yang lebih spesifik.
Dalam pemrograman berorientasi objek kami membuat objek (yang merupakan abstraksi entitas dunia nyata) dan kami menggunakan kelas atau prototipe untuk membuat generalisasi objek ini. Generalisasi dibuat melalui pewarisan. Sepeda adalah generalisasi sepeda lumpur. Karenanya sepeda lumpur diwarisi dari sepeda.
Pemrograman Berorientasi Objek Klasik
Dalam pemrograman berorientasi objek klasik kita memiliki dua jenis abstraksi: kelas dan objek. Sebuah objek, seperti yang disebutkan sebelumnya, adalah abstraksi dari entitas dunia nyata. Kelas di sisi lain adalah abstraksi dari suatu objek atau kelas lain (yaitu generalisasi). Misalnya, pertimbangkan:
+----------------------+----------------+---------------------------------------+
| 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. |
+----------------------+----------------+---------------------------------------+
Seperti yang Anda lihat dalam bahasa pemrograman berorientasi objek klasik, objek hanyalah abstraksi (yaitu semua objek memiliki tingkat abstraksi 1) dan kelas hanya generalisasi (yaitu semua kelas memiliki tingkat abstraksi lebih besar dari 1).
Objek dalam bahasa pemrograman berorientasi objek klasik hanya dapat dibuat dengan membuat instance kelas:
class Human {
// ...
}
class Man extends Human {
// ...
}
Man johnDoe = new Man();
Dalam penjumlahan dalam bahasa pemrograman berorientasi objek klasik, objek adalah abstraksi dari entitas dunia nyata dan kelas adalah generalisasi (yaitu abstraksi dari objek atau kelas lain).
Oleh karena itu, ketika tingkat abstraksi meningkat, entitas menjadi lebih umum dan ketika tingkat abstraksi menurun, entitas menjadi lebih spesifik. Dalam pengertian ini, tingkat abstraksi dapat dianalogikan dengan skala yang berkisar dari entitas yang lebih spesifik hingga entitas yang lebih umum.
Pemrograman Berorientasi Objek Prototipe
Bahasa pemrograman berorientasi objek prototypal jauh lebih sederhana daripada bahasa pemrograman berorientasi objek klasik karena dalam pemrograman berorientasi objek prototypal kita hanya memiliki satu jenis abstraksi (yaitu objek). Misalnya, pertimbangkan:
+----------------------+----------------+---------------------------------------+
| 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. |
+----------------------+----------------+---------------------------------------+
Seperti yang Anda lihat dalam bahasa pemrograman berorientasi objek prototipe objek adalah abstraksi dari entitas dunia nyata (dalam hal ini mereka hanya disebut objek) atau objek lain (dalam hal ini mereka disebut prototipe objek yang mereka abstrak). Karenanya prototipe adalah generalisasi.
Objek dalam prototipe bahasa pemrograman berorientasi objek dapat dibuat baik ex-nihilo (yaitu dari ketiadaan) atau dari objek lain (yang menjadi prototipe dari objek yang baru dibuat):
var human = {};
var man = Object.create(human);
var johnDoe = Object.create(man);
Menurut pendapat saya, bahasa pemrograman berorientasi objek prototipe lebih kuat daripada bahasa pemrograman berorientasi objek klasik karena:
- Hanya ada satu jenis abstraksi.
- Generalisasi hanyalah objek.
Sekarang Anda pasti sudah menyadari perbedaan antara warisan klasik dan warisan prototipe. Pewarisan klasik terbatas pada kelas yang diturunkan dari kelas lain. Namun pewarisan prototipe tidak hanya mencakup prototipe yang diwarisi dari prototipe lain tetapi juga objek yang diwarisi dari prototipe.
Isomorfisme Kelas Prototipe
Anda pasti telah memperhatikan bahwa prototipe dan kelas sangat mirip. Itu benar. Mereka. Faktanya mereka sangat mirip sehingga Anda benar-benar dapat menggunakan prototipe untuk memodelkan kelas:
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;
}
}
Dengan menggunakan CLASS
fungsi di atas, Anda dapat membuat prototipe yang terlihat seperti kelas:
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));
Namun kebalikannya tidak benar (yaitu Anda tidak dapat menggunakan kelas untuk memodelkan prototipe). Ini karena prototipe adalah objek tetapi kelas bukan objek. Mereka adalah jenis abstraksi yang sama sekali berbeda.
Kesimpulan
Kesimpulannya, kita belajar bahwa abstraksi adalah "konsep umum yang dibentuk dengan mengekstraksi fitur umum dari contoh tertentu" dan generalisasi itu adalah "abstraksi dari abstraksi yang lebih spesifik" . Kami juga belajar tentang perbedaan antara warisan prototipe dan klasik dan bagaimana keduanya adalah dua sisi dari koin yang sama.
Pada catatan perpisahan saya ingin menyampaikan bahwa ada dua pola warisan prototipe: pola prototipe dan pola konstruktor. Pola prototypal adalah pola pewarisan prototipal sedangkan pola konstruktor digunakan untuk membuat pewarisan prototip lebih mirip dengan pewarisan klasik. Secara pribadi saya lebih suka pola prototipe.
PS Saya orang yang menulis posting blog " Why Prototypal Inheritance Matters " dan menjawab pertanyaan " Manfaat warisan prototypal daripada klasik? ". Jawaban saya adalah jawaban yang diterima.