Saya sedang belajar cara membuat OOP dengan JavaScript . Apakah ia memiliki konsep antarmuka (seperti Java interface
)?
Jadi saya bisa membuat pendengar ...
javascript
oop
Tom Brito
sumber
sumber
Jawaban:
Tidak ada anggapan "kelas ini harus memiliki fungsi-fungsi ini" (yaitu, tidak ada antarmuka per se), karena:
Sebaliknya, JavaScript menggunakan apa yang disebut bebek mengetik . (Jika berjalan seperti bebek, dan dukun seperti bebek, sejauh JS peduli, itu bebek.) Jika objek Anda memiliki duri (), metode berjalan (), dan terbang (), kode dapat menggunakannya di mana pun ia harapkan sebuah objek yang dapat berjalan, dukun, dan terbang, tanpa memerlukan implementasi beberapa antarmuka "Duckable". Antarmuka persis set fungsi yang menggunakan kode (dan nilai pengembalian dari fungsi-fungsi), dan dengan mengetik bebek, Anda mendapatkannya secara gratis.
Sekarang, bukan berarti kode Anda tidak akan gagal setengah jalan, jika Anda mencoba menelepon
some_dog.quack()
; Anda akan mendapatkan TypeError. Terus terang, jika Anda memberitahu anjing untuk dukun, Anda memiliki masalah yang sedikit lebih besar; Mengetik bebek bekerja paling baik ketika Anda menjaga semua bebek Anda berturut-turut, sehingga untuk berbicara, dan tidak membiarkan anjing dan bebek berbaur bersama kecuali Anda memperlakukan mereka sebagai hewan generik. Dengan kata lain, meskipun antarmuka itu cair, masih ada di sana; sering kali kesalahan menularkan anjing ke kode yang mengharapkannya untuk dukun dan terbang di tempat pertama.Tetapi jika Anda yakin telah melakukan hal yang benar, Anda dapat mengatasi masalah anjing dukun dengan menguji keberadaan metode tertentu sebelum mencoba menggunakannya. Sesuatu seperti
Jadi, Anda dapat memeriksa semua metode yang dapat Anda gunakan sebelum menggunakannya. Sintaksnya agak jelek. Ada cara yang sedikit lebih cantik:
Ini adalah JavaScript standar, jadi itu harus bekerja pada penerjemah JS apa pun yang layak digunakan. Ini memiliki manfaat tambahan membaca seperti bahasa Inggris.
Untuk peramban modern (artinya, hampir semua peramban selain IE 6-8), bahkan ada cara untuk menjaga agar properti tidak muncul
for...in
:Masalahnya adalah bahwa objek IE7 tidak memiliki
.defineProperty
sama sekali, dan di IE8, itu diduga hanya bekerja pada objek host (yaitu, elemen DOM dan semacamnya). Jika kompatibilitas merupakan masalah, Anda tidak dapat menggunakan.defineProperty
. (Saya bahkan tidak akan menyebutkan IE6, karena agak tidak relevan lagi di luar China.)Masalah lain adalah bahwa beberapa gaya pengkodean suka berasumsi bahwa setiap orang menulis kode yang buruk, dan melarang memodifikasi
Object.prototype
jika seseorang ingin menggunakan secara membabi butafor...in
. Jika Anda peduli tentang itu, atau menggunakan kode ( rusak IMO ), coba versi yang sedikit berbeda:sumber
for...in
adalah - dan selalu - penuh dengan bahaya seperti itu, dan siapa pun yang melakukannya tanpa setidaknya mempertimbangkan bahwa seseorang ditambahkan keObject.prototype
(teknik yang tidak biasa, dengan pengakuan artikel itu sendiri) akan melihat kode mereka rusak di tangan orang lain.for...in
masalah. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…for...in
masalah" masih akan ada sampai taraf tertentu, karena akan selalu ada kode ceroboh ... baik, itu, danObject.defineProperty(obj, 'a', {writable: true, enumerable: false, value: 3});
sedikit lebih banyak pekerjaan daripada sekadarobj.a = 3;
. Saya benar-benar dapat memahami orang yang tidak berusaha melakukannya lebih sering. : PAmbil salinan ' pola desain JavaScript ' oleh Dustin Diaz . Ada beberapa bab yang didedikasikan untuk mengimplementasikan antarmuka JavaScript melalui Duck Typing. Ini bacaan yang bagus juga. Tapi tidak, tidak ada implementasi bahasa asli antarmuka, Anda harus Duck Type .
sumber
JavaScript (ECMAScript edition 3)
implements
menyimpan kata yang disimpan untuk digunakan di masa mendatang . Saya pikir ini dimaksudkan persis untuk tujuan ini, namun, dengan tergesa-gesa untuk mendapatkan spesifikasi keluar dari pintu mereka tidak punya waktu untuk menentukan apa yang harus dilakukan dengan itu, jadi, pada saat ini, browser tidak melakukan apa pun selain biarkan duduk di sana dan sesekali mengeluh jika Anda mencoba menggunakannya untuk sesuatu.Adalah mungkin dan memang cukup mudah untuk membuat
Object.implement(Interface)
metode Anda sendiri dengan logika yang muncul setiap kali set properti / fungsi tertentu tidak diimplementasikan dalam objek tertentu.Saya menulis artikel tentang orientasi objek di mana menggunakan notasi saya sendiri sebagai berikut :
Ada banyak cara untuk menguliti kucing khusus ini, tetapi ini adalah logika yang saya gunakan untuk implementasi Antarmuka saya sendiri. Saya menemukan saya lebih suka pendekatan ini, dan mudah dibaca dan digunakan (seperti yang Anda lihat di atas). Itu berarti menambahkan metode 'implement' di
Function.prototype
mana beberapa orang mungkin memiliki masalah dengan, tetapi saya menemukan itu berfungsi dengan baik.sumber
var interf = arguments[i]; for (prop in interf) { if (this.prototype[prop] === undefined) { throw 'Member [' + prop + '] missing from class definition.'; }}
. Lihat bagian bawah tautan artikel untuk contoh yang lebih rumit.Antarmuka JavaScript:
Meskipun JavaScript tidak memiliki
interface
tipe, seringkali diperlukan. Untuk alasan yang berkaitan dengan sifat dinamis JavaScript dan penggunaan Prototypical-Inheritance, sulit untuk memastikan antarmuka yang konsisten di seluruh kelas - namun, dimungkinkan untuk melakukannya; dan sering ditiru.Pada titik ini, ada beberapa cara tertentu untuk meniru Antarmuka dalam JavaScript; varians pada pendekatan biasanya memuaskan beberapa kebutuhan, sementara yang lain tidak tersentuh. Seringkali, pendekatan yang paling kuat terlalu rumit dan menghalangi implementor (pengembang).
Berikut adalah pendekatan untuk Kelas Antarmuka / Abstrak yang tidak terlalu rumit, eksplikatif, menjaga implementasi dalam Abstraksi seminimal mungkin, dan menyisakan ruang yang cukup untuk metodologi dinamis atau khusus:
Peserta
Penyelesai Sila
The
resolvePrecept
fungsi adalah fungsi utilitas & pembantu untuk menggunakan dalam Anda Kelas Abstrak . Tugasnya adalah untuk memungkinkan implementasi khusus - penanganan Sila yang dienkapsulasi (data & perilaku) . Itu bisa melempar kesalahan atau memperingatkan - DAN - menetapkan nilai default ke kelas Implementor.iAbstractClass
The
iAbstractClass
mendefinisikan interface yang akan digunakan. Pendekatannya memerlukan perjanjian diam-diam dengan kelas implementornya. Antarmuka ini menetapkan setiap sila ke namespace sila persis yang sama - ATAU - untuk apa pun yang dihasilkan fungsi Precept Resolver . Namun, perjanjian diam-diam memutuskan untuk konteks - ketentuan Pelaksana.Pelaksana
The Pelaksana hanya 'setuju' dengan Interface ( iAbstractClass dalam kasus ini) dan menerapkannya dengan menggunakan Constructor-Pembajakan :
iAbstractClass.apply(this)
. Dengan mendefinisikan data & perilaku di atas, dan kemudian membajak konstruktor Antarmuka - meneruskan konteks Implementor ke konstruktor Antarmuka - kami dapat memastikan bahwa penggantian Implementor akan ditambahkan, dan bahwa Antarmuka akan menjelaskan peringatan dan nilai default.Ini adalah pendekatan yang sangat tidak rumit yang telah melayani tim saya & saya sangat baik selama perjalanan waktu dan proyek yang berbeda. Namun, itu memang memiliki beberapa peringatan & kekurangan.
Kekurangannya
Meskipun ini membantu menerapkan konsistensi di seluruh perangkat lunak Anda ke tingkat yang signifikan, ini tidak mengimplementasikan antarmuka yang sebenarnya - tetapi mengemulasi mereka. Meskipun definisi, default, dan peringatan atau kesalahan yang explicated, yang penjelasan penggunaan yang ditegakkan & menegaskan oleh pengembang (seperti dengan banyak pengembangan JavaScript).
Tampaknya ini adalah pendekatan terbaik untuk "Antarmuka dalam JavaScript" , namun, saya ingin melihat yang berikut ini terselesaikan:
delete
tindakanYang mengatakan, saya harap ini membantu Anda sebanyak tim saya dan saya.
sumber
Anda memerlukan antarmuka di Java karena diketik secara statis dan kontrak antara kelas harus diketahui selama kompilasi. Dalam JavaScript berbeda. JavaScript diketik secara dinamis; itu berarti bahwa ketika Anda mendapatkan objek Anda hanya dapat memeriksa apakah ia memiliki metode tertentu dan menyebutnya.
sumber
yourMethod
pada entri # 5 diSuperclass
vtable, dan untuk setiap subkelas yang memiliki sendiriyourMethod
, cukup tunjukkan bahwa entri subkelas # 5 pada implementasi yang sesuai.Implementation
yang mengimplementasikanSomeInterface
tidak hanya mengatakan itu mengimplementasikan seluruh antarmuka. Ini memiliki info yang mengatakan "Saya mengimplementasikanSomeInterface.yourMethod
" dan menunjuk pada definisi metode untukImplementation.yourMethod
. Ketika panggilan JVMSomeInterface.yourMethod
, itu terlihat di kelas untuk info tentang implementasi metode antarmuka itu, dan menemukan itu perlu untuk memanggilImplementation.yourMethod
.Harapan, bahwa siapa pun yang masih mencari jawaban merasa terbantu.
Anda dapat mencoba menggunakan Proksi (Ini adalah standar sejak ECMAScript 2015): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
Maka Anda dapat dengan mudah mengatakan:
sumber
Ketika Anda ingin menggunakan transcompiler, maka Anda bisa mencoba TypeScript. Ini mendukung rancangan fitur ECMA (dalam proposal, antarmuka disebut " protokol ") mirip dengan apa yang dilakukan bahasa seperti coffeescript atau babel.
Di TypeScript antarmuka Anda dapat terlihat seperti:
Apa yang tidak bisa Anda lakukan:
sumber
tidak ada antarmuka asli dalam JavaScript, ada beberapa cara untuk mensimulasikan antarmuka. saya telah menulis paket yang melakukannya
Anda dapat melihat implantasi di sini
sumber
Javascript tidak memiliki antarmuka. Tapi itu bisa diketik bebek, contohnya bisa ditemukan di sini:
http://reinsbrain.blogspot.com/2008/10/interface-in-javascript.html
sumber
Saya tahu ini adalah yang lama, tetapi saya baru-baru ini menemukan diri saya membutuhkan lebih dan lebih untuk memiliki API yang berguna untuk memeriksa objek terhadap antarmuka. Jadi saya menulis ini: https://github.com/tomhicks/methodical
Ini juga tersedia melalui NPM:
npm install methodical
Ini pada dasarnya melakukan semua yang disarankan di atas, dengan beberapa opsi untuk menjadi sedikit lebih ketat, dan semua tanpa harus melakukan banyak
if (typeof x.method === 'function')
boilerplate.Semoga ada yang merasa bermanfaat.
sumber
Ini adalah pertanyaan lama, namun topik ini tidak pernah berhenti menggangguku.
Karena banyak jawaban di sini dan di seluruh web fokus pada "menegakkan" antarmuka, saya ingin menyarankan pandangan alternatif:
Sebagai contoh, saya memiliki Generator Email yang mengharapkan untuk menerima Pabrik Bagian Email , yang "tahu" bagaimana menghasilkan konten bagian dan HTML. Karenanya, mereka semua perlu memiliki semacam
getContent(id)
dangetHtml(content)
metode.Tantangan utama dengan pola ini adalah bahwa metode harus
static
, atau untuk mendapatkan sebagai argumen instance itu sendiri, untuk mengakses propertinya. Namun ada beberapa kasus di mana saya menemukan pertukaran ini sepadan dengan kerumitan.sumber
antarmuka abstrak seperti ini
buat sebuah instance:
dan gunakan itu
sumber