Katakanlah Anda memiliki kode di bawah ini:
function A() {
function modify() {
x = 300;
y = 400;
}
var c = new C();
}
function B() {
function modify(){
x = 3000;
y = 4000;
}
var c = new C();
}
C = function () {
var x = 10;
var y = 20;
function modify() {
x = 30;
y = 40;
};
modify();
alert("The sum is: " + (x+y));
}
Sekarang pertanyaannya adalah, jika ada cara di mana saya bisa mengganti metode modify
dari C
dengan metode yang ada di A
dan B
. Di Java Anda akan menggunakan super
-keyword, tetapi bagaimana Anda bisa mencapai sesuatu seperti ini di JavaScript?
javascript
oop
overriding
Daniel Nastase
sumber
sumber
modify
bukan metode tetapi fungsi bersarang - ada perbedaan antara keduanya ...super
kata kunci untuk mengakses bidang non-privat dan metode kelas-super. Anda tidak menggunakannya untuk menimpanya.Jawaban:
Sunting: Sekarang enam tahun sejak jawaban asli ditulis dan banyak yang telah berubah!
Semoga berhasil!
Warisan JavaScript terlihat sedikit berbeda dari Java. Berikut adalah tampilan sistem objek JavaScript asli:
// Create a class function Vehicle(color){ this.color = color; } // Add an instance method Vehicle.prototype.go = function(){ return "Underway in " + this.color; } // Add a second class function Car(color){ this.color = color; } // And declare it is a subclass of the first Car.prototype = new Vehicle(); // Override the instance method Car.prototype.go = function(){ return Vehicle.prototype.go.call(this) + " car" } // Create some instances and see the overridden behavior. var v = new Vehicle("blue"); v.go() // "Underway in blue" var c = new Car("red"); c.go() // "Underway in red car"
Sayangnya ini agak jelek dan tidak termasuk cara yang sangat bagus untuk "super": Anda harus secara manual menentukan metode kelas induk mana yang ingin Anda panggil. Hasilnya, ada berbagai alat untuk membuat kelas menjadi lebih baik. Coba lihat Prototype.js, Backbone.js, atau pustaka serupa yang menyertakan sintaks yang lebih baik untuk melakukan OOP di js.
sumber
Karena ini adalah hit teratas di Google, saya ingin memberikan jawaban yang diperbarui.
Menggunakan kelas ES6 membuat pewarisan dan penggantian metode jauh lebih mudah:
'use strict'; class A { speak() { console.log("I'm A"); } } class B extends A { speak() { super.speak(); console.log("I'm B"); } } var a = new A(); a.speak(); // Output: // I'm A var b = new B(); b.speak(); // Output: // I'm A // I'm B
Kata
super
kunci mengacu pada kelas induk saat digunakan dalam kelas pewarisan. Selain itu, semua metode di kelas induk terikat ke instance anak, jadi Anda tidak perlu menulissuper.method.apply(this);
.Mengenai kompatibilitas: tabel kompatibilitas ES6 hanya menampilkan versi terbaru dari kelas dukungan pemain utama (kebanyakan). Browser V8 telah memilikinya sejak Januari tahun ini (Chrome dan Opera), dan Firefox, menggunakan mesin SpiderMonkey JS, akan melihat kelas bulan depan dengan rilis resmi Firefox 45 mereka. Di sisi seluler, Android masih belum mendukung fitur ini, sedangkan iOS 9 yang rilis lima bulan lalu, memiliki dukungan parsial.
Untungnya, ada Babel , pustaka JS untuk mengompilasi ulang kode Harmony menjadi kode ES5. Classes, dan banyak fitur keren lainnya di ES6 dapat membuat kode Javascript Anda lebih mudah dibaca dan dipelihara.
sumber
Once harus menghindari meniru OO klasik dan sebagai gantinya gunakan OO prototipe. Pustaka utilitas yang bagus untuk prototipe OO adalah ciri .
Daripada menimpa metode dan menyiapkan rantai pewarisan (seseorang harus selalu menyukai komposisi objek daripada pewarisan objek), Anda harus menggabungkan fungsi yang dapat digunakan kembali menjadi ciri-ciri dan membuat objek dengannya.
Contoh Langsung
var modifyA = { modify: function() { this.x = 300; this.y = 400; } }; var modifyB = { modify: function() { this.x = 3000; this.y = 4000; } }; C = function(trait) { var o = Object.create(Object.prototype, Trait(trait)); o.modify(); console.log("sum : " + (o.x + o.y)); return o; } //C(modifyA); C(modifyB);
sumber
modifikasikan () dalam contoh Anda adalah fungsi pribadi, yang tidak akan dapat diakses dari mana pun kecuali dalam definisi A, B, atau C Anda. Anda harus mendeklarasikannya sebagai
this.modify = function(){}
C tidak memiliki referensi ke orang tuanya, kecuali Anda meneruskannya ke C. Jika C diatur untuk mewarisi dari A atau B, C akan mewarisi metode publiknya (bukan fungsi pribadinya seperti yang telah Anda modifikasi () tentukan). Setelah C mewarisi metode dari induknya, Anda dapat mengganti metode yang diwariskan.
sumber
metode
modify()
yang Anda panggil terakhir kali dipanggil dalam konteks global jika Anda ingin menimpanya,modify()
Anda harus mewarisiA
atauB
.Mungkin Anda mencoba melakukan ini:
Dalam hal ini
C
mewarisiA
function A() { this.modify = function() { alert("in A"); } } function B() { this.modify = function() { alert("in B"); } } C = function() { this.modify = function() { alert("in C"); }; C.prototype.modify(); // you can call this method where you need to call modify of the parent class } C.prototype = new A();
sumber
C.prototype.modify()
akan memiliki nilai yang salahthis
. YaituC.prototype
sebagai pengganti contoh c. Silakan gunakan.call(this)
tapi kemudian jawaban Anda hanya duplikat :)Tidak, kecuali jika Anda membuat semua variabel "publik", yaitu menjadikannya anggota
Function
baik secara langsung atau melaluiprototype
properti.var C = function( ) { this.x = 10 , this.y = 20 ; this.modify = function( ) { this.x = 30 , this.y = 40 ; console.log("(!) C >> " + (this.x + this.y) ) ; } ; } ; var A = function( ) { this.modify = function( ) { this.x = 300 , this.y = 400 ; console.log("(!) A >> " + (this.x + this.y) ) ; } ; } ; A.prototype = new C ; var B = function( ) { this.modify = function( ) { this.x = 3000 , this.y = 4000 ; console.log("(!) B >> " + (this.x + this.y) ) ; } ; } ; new C( ).modify( ) ; new A( ).modify( ) ; new B( ).modify( ) ;
Anda akan melihat beberapa perubahan.
Yang terpenting, panggilan ke konstruktor "kelas super" yang seharusnya sekarang tersirat dalam baris ini:
<name>.prototype = new C ;
Kedua
A
danB
sekarang akan memiliki dimodifikasi secara individu anggotax
dany
yang tidak akan terjadi jika kita akan menulis... = C
sebagai gantinya.Kemudian,
x
,y
danmodify
semua "publik" anggota agar menetapkan berbedaFunction
untuk mereka<name>.prototype.modify = function( ) { /* ... */ }
akan "menimpa" yang asli
Function
dengan nama itu.Terakhir, panggilan ke
modify
tidak bisa dilakukan diFunction
deklarasi karena panggilan implisit ke "super-class" kemudian akan dijalankan lagi saat kita menetapkan "super-class"prototype
yang seharusnya ke properti "sub-class" yang seharusnya.Tapi begini, kurang lebih begini cara Anda melakukan hal semacam ini di JavaScript.
HTH,
FK
sumber
<name>.prototype = new C;
membayangi semua anggota prototipeObjects
akan berbagi anggota yang samaC
jika Anda tidak membuat instanceC
Object. Dengan demikian, perubahanx
dalamA
akan berubahx
diC
dan dengan demikian mengubahx
diB
. Yang jelas tidak diinginkan.A
danB
mewarisi dariC
. Jika garis itu hilang, itu tidak akan menjadi masalah. Pada kenyataannya, satu-satunya prototipeA
dan jugaB
"bayangan" akan memiliki akses ke dalam kasus ituObject.prototype
.x
,y
danmodify
sehingga bayangan semuaC
anggota 's. Apa gunanya meletakkan C dalam prototipe jika Anda tidak menggunakannya? Itu kode mati.function A() { var c = new C(); c.modify = function(){ c.x = 123; c.y = 333; } c.sum(); } function B() { var c = new C(); c.modify = function(){ c.x = 999; c.y = 333; } c.sum(); } C = function () { this.x = 10; this.y = 20; this.modify = function() { this.x = 30; this.y = 40; }; this.sum = function(){ this.modify(); console.log("The sum is: " + (this.x+this.y)); } } A(); B();
sumber