Saya telah melakukan sebagian besar penelitian saya tentang ini pada BabelJS dan MDN (yang tidak memiliki informasi sama sekali), tetapi jangan ragu untuk memberi tahu saya jika saya belum cukup berhati-hati dalam mencari-cari informasi lebih lanjut tentang ES6 Spec.
Saya bertanya-tanya apakah ES6 mendukung multiple inheritance dengan cara yang sama seperti bahasa-bahasa yang diketik bebek lainnya. Misalnya, dapatkah saya melakukan sesuatu seperti:
class Example extends ClassOne, ClassTwo {
constructor() {
}
}
untuk memperpanjang beberapa kelas ke kelas baru? Jika demikian, apakah interpreter lebih suka metode / properti dari ClassTwo daripada ClassOne?
Jawaban:
Suatu objek hanya dapat memiliki satu prototipe. Mewarisi dari dua kelas dapat dilakukan dengan membuat objek induk sebagai kombinasi dari dua prototipe induk.
Sintaks untuk subklas memungkinkan untuk melakukan itu dalam deklarasi, karena sisi kanan
extends
klausa dapat berupa ekspresi apa pun. Dengan demikian, Anda dapat menulis fungsi yang menggabungkan prototipe sesuai dengan kriteria apa pun yang Anda suka, dan memanggil fungsi itu dalam deklarasi kelas.sumber
__proto__
tautan untuk meneruskan pencarian prop ke objek yang benar? Saya sudah mencoba tetapi belum pernah berhasil__proto__
itu sendiri adalah fitur usang. Hal ini mencerminkan link prototipe internal, tetapi itu tidak benar-benar link prototipe internal.class Foo extends new MultiClass(Bar, Baz, One, Two) { ... }
. Metode dan properti dari konstruktor terakhir yang dilewatinew MultiClass
memiliki prioritas tertinggi, mereka hanya dicampur ke dalam prototipe baru. Saya pikir ada solusi yang lebih baik jika diimplementasikan kembali menggunakan ES6 Proxies, tetapi belum ada dukungan asli yang cukup untuk itu.Lihat contoh saya di bawah ini,
super
metode yang berfungsi seperti yang diharapkan. Menggunakan beberapa trik bahkaninstanceof
berhasil (sebagian besar waktu):Akan dicetak
Tautan ke biola di sekitar
sumber
(B||Object)
.F extends (B||Object)
bukanF extends B(Object)
, itu akan memperpanjang B mixin seperti itu (sebagai fungsi) sehingga F hanya akan memperpanjang prototipe Fungsi default karena B tidak pernah dieksekusi. Dengan menggunakanF extends B(Object)
kita sebenarnya mengeksekusi fungsi B dan F akan memperluas fungsi B 'apa pun' yang kembali, dalam hal ini adalah kelas B yang didefinisikan di dalam fungsi B ... peretasan kecil untuk menjaga penamaan kelas tetap benar.const B = (B = Object) => class extends B {
dan kemudian gunakanclass F extends B() {
untuk penggunaan yang lebih cantik, tapi hack yang lebih buruk Kappaconst B = (B) => class extends (B||Object) {
akan membiarkan Anda menggantinyainst5 = new (B(Object)); // instance only B, ugly format
denganinst5 = new (B());
, atau mungkin saya salah memahami konteks ...console.log('from B -> inside instance of B: ${this instanceof B}');
penyihir akan gagalRight-hand side of 'instanceof' is not an object
. Menggunakanconst B = (B = Object) => class extends B {
seperti yang disebutkan sebelumnya akan lulus dari contoh tes dan memberi Andainst5 = new (B());
penggunaan juga jika Anda menginginkannya.Implementasi Sergio Carneiro dan Jon mengharuskan Anda untuk mendefinisikan fungsi initializer untuk semua kecuali satu kelas. Berikut adalah versi modifikasi dari fungsi agregasi, yang menggunakan parameter default di konstruktor sebagai gantinya. Termasuk juga beberapa komentar oleh saya.
Ini sedikit demo:
Fungsi agregasi ini akan memilih properti dan metode kelas yang muncul kemudian dalam daftar kelas.
sumber
Component
, itu tidak berfungsi. hanya FYI untuk orang lain yang mungkin menginginkannya untuk tujuan ini.Justin Fagnani menjelaskan cara yang sangat bersih (imho) untuk menyusun beberapa kelas menjadi satu menggunakan fakta bahwa dalam ES2015, kelas dapat dibuat dengan ekspresi kelas .
Ekspresi vs deklarasi
Pada dasarnya, sama seperti Anda dapat membuat fungsi dengan ekspresi:
Anda dapat melakukan hal yang sama dengan kelas:
Ekspresi dievaluasi saat runtime, ketika kode dijalankan, sedangkan deklarasi dieksekusi sebelumnya.
Menggunakan ekspresi kelas untuk membuat mixin
Anda bisa menggunakan ini untuk membuat fungsi yang secara dinamis membuat kelas hanya ketika fungsi dipanggil:
Hal yang paling keren tentang itu adalah Anda dapat mendefinisikan seluruh kelas sebelumnya dan hanya memutuskan kelas mana yang harus diperluas pada saat Anda memanggil fungsi:
Jika Anda ingin menggabungkan beberapa kelas bersama, karena kelas ES6 hanya mendukung pewarisan tunggal, Anda perlu membuat rantai kelas yang berisi semua kelas yang ingin Anda campur bersama. Jadi katakanlah Anda ingin membuat kelas C yang memanjang A dan B, Anda bisa melakukan ini:
Masalahnya adalah ini sangat statis. Jika nanti Anda memutuskan ingin membuat kelas D yang memanjang B tetapi tidak A, Anda punya masalah.
Tetapi dengan beberapa tipuan cerdas menggunakan fakta bahwa kelas dapat menjadi ekspresi, Anda dapat menyelesaikan ini dengan membuat A dan B tidak secara langsung sebagai kelas, tetapi sebagai pabrik kelas (menggunakan fungsi panah untuk singkatnya):
Perhatikan bagaimana kita hanya memutuskan pada saat terakhir kelas mana yang termasuk dalam hierarki.
sumber
Ini tidak mungkin dilakukan dengan cara kerja pewarisan prototipikal. Mari kita lihat bagaimana alat peraga warisan bekerja di js
mari kita lihat apa yang terjadi ketika Anda mengakses properti yang tidak ada:
Anda dapat menggunakan mixin untuk mendapatkan beberapa fungsi itu tetapi Anda tidak akan terlambat mengikat:
vs.
sumber
Saya akan datang dengan solusi ini:
pemakaian:
Selama Anda membuat trik ini dengan kelas yang ditulis khusus Anda, itu bisa dirantai. tetapi kami segera setelah Anda ingin memperpanjang beberapa fungsi / kelas yang ditulis tidak seperti itu - Anda tidak akan memiliki kesempatan untuk melanjutkan lingkaran.
berfungsi untuk saya di simpul v5.4.1 dengan --harmony flag
sumber
Dari halaman es6-features.org/#ClassInheritanceFromExpressions , dimungkinkan untuk menulis fungsi agregasi untuk memungkinkan pewarisan berganda:
Tapi itu sudah disediakan di perpustakaan seperti agregasi .
sumber
gunakan Mixins untuk ES6 multiple Inheritence.
sumber
one class inherits from 2 or more unrelated classes
? Apa contoh Anda menunjukkan adalah satu kelas yang mewarisi dari 2, tetapi kelas terkait. Ini adalah warisan tunggal, bukan warisan ganda.classTwo
. Karena tidak memiliki konsep kelas yang asli, JS tidak memiliki warisan struktural . Begitu saja saya tidak dapat membayangkan skenario JS di mana mixin berperilaku berbeda dari apa yang Anda harapkan mengonseptualisasikan mereka sebagai MI dari dunia OO yang sebenarnya (terlepas dari rantai 'super' yang ditentukan); mungkin beberapa orang lebih berpengetahuan daripada saya dapat menyediakan satu.Nah Object.assign memberi Anda kemungkinan untuk melakukan sesuatu yang dekat meskipun sedikit lebih mirip komposisi dengan kelas ES6.
Saya belum pernah melihat ini digunakan di mana pun tetapi sebenarnya cukup berguna. Kamu bisa memakai
function shark(){}
bukan kelas tetapi ada keuntungan menggunakan kelas sebagai gantinya.Saya percaya satu-satunya hal yang berbeda dengan pewarisan dengan
extend
kata kunci adalah bahwa fungsinya tidak hanya hidup padaprototype
tetapi juga objek itu sendiri.Jadi sekarang ketika Anda melakukannya
new Shark()
yangshark
dibuat memilikibite
metode, sementara hanya prototipe yang memilikieat
metodesumber
Tidak ada cara mudah untuk melakukan multiple class inheritance. Saya mengikuti kombinasi asosiasi dan warisan untuk mencapai perilaku semacam ini.
Semoga ini bisa membantu.
sumber
Solusi ES6 ini bekerja untuk saya:
multiple-inheritance.js
main.js
Hasil di konsol browser:
sumber
Saya menghabiskan setengah minggu mencoba mencari tahu sendiri, dan menulis seluruh artikel tentang itu, https://github.com/latitov/OOP_MI_Ct_oPlus_in_JS , dan berharap itu membantu beberapa dari Anda.
Singkatnya, inilah cara MI dapat diterapkan dalam JavaScript:
Dan inilah spesialisasi_dengan () satu-baris:
Sekali lagi, silakan lihat di https://github.com/latitov/OOP_MI_Ct_oPlus_in_JS .
sumber
dalam javascript Anda tidak dapat memberikan ke kelas (fungsi konstruktor) 2 objek prototipe yang berbeda dan karena warisan dalam pekerjaan javascript dengan prototipe jadi Anda tidak dapat menggunakan lebih dari 1 warisan untuk satu kelas tetapi Anda dapat menggabungkan dan bergabung dengan properti objek Prototipe dan properti utama itu di dalam kelas secara manual dengan refactoring yang kelas induk dan selanjutnya memperluas versi baru dan bergabung dengan kelas target Anda memiliki kode untuk pertanyaan Anda:
sumber
Jawaban saya sepertinya kurang kode dan berfungsi untuk saya:
sumber
gunakan tingkat dengan fungsi kustom untuk menangani banyak warisan dengan ES6
sumber
Saya akan menambahkan solusi saya juga - saya menemukan itu yang paling ramah untuk diri saya sendiri dari apa yang saya baca di utas ini.
Anda dapat menggunakannya kemudian seperti ini:
sumber
Sebagai bukti konsep, saya melakukan fungsi berikut. Dibutuhkan daftar kelas dan menyusunnya menjadi kelas baru (prototipe terakhir menang sehingga tidak ada konflik). Saat membuat fungsi tersusun, pengguna dapat memilih untuk menggunakan semua konstruktor asli [ sic! ] atau lulus sendiri. Ini adalah tantangan terbesar dari eksperimen ini: untuk menghasilkan deskripsi tentang apa yang harus dilakukan oleh konstruktor. Menyalin metode ke dalam prototipe bukanlah masalah, tetapi apa yang dimaksud dengan logika objek yang baru dikomposisikan. Atau mungkin harus tanpa konstruktor? Dalam Python, dari yang saya tahu, ia menemukan yang cocok konstruktor yang tetapi fungsi dalam JS lebih menerima, maka seseorang dapat beralih ke fungsi apa saja dan dari tanda tangan itu tidak akan jelas.
Saya tidak berpikir itu dioptimalkan tetapi tujuannya mengeksplorasi kemungkinan.
instanceof
tidak akan berperilaku seperti yang diharapkan yang, saya kira, mengecewakan, karena pengembang berorientasi kelas suka menggunakan ini sebagai alat.Mungkin JavaScript tidak memilikinya.
Awalnya diposting di sini (gist.github.com).
sumber
https://www.npmjs.com/package/ts-mixer
Dengan dukungan TS terbaik dan banyak fitur bermanfaat lainnya!
sumber
Inilah cara yang mengagumkan / sangat jelek untuk memperluas beberapa kelas. Saya menggunakan beberapa fungsi yang dimasukkan Babel ke dalam kode yang saya transkrip. Fungsi menciptakan kelas baru yang mewarisi class1, dan class1 mewarisi class2, dan seterusnya. Ini memiliki masalah, tetapi ide yang menyenangkan.
sumber