Powiedzmy, że masz poniższy kod:
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));
}
Nasuwa się pytanie, czy istnieje jakikolwiek sposób, w jaki mogę zastąpić metodę modify
od C
z metodami, które są w A
i B
. W Javie super
użyłbyś -klucza kluczowego, ale jak możesz osiągnąć coś takiego w JavaScript?
javascript
oop
overriding
Daniel Nastase
źródło
źródło
modify
nie jest metodą, ale funkcją zagnieżdżoną - jest różnica między tymi dwoma ...super
słowa kluczowego, aby uzyskać dostęp do nieprywatnych pól i metod superklasy. Nie używasz go do ich zastępowania.Odpowiedzi:
Edycja: minęło już sześć lat od napisania oryginalnej odpowiedzi i wiele się zmieniło!
Powodzenia!
Dziedziczenie JavaScript wygląda nieco inaczej niż Java. Oto jak wygląda natywny system obiektów JavaScript:
// 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"
Niestety jest to trochę brzydkie i nie zawiera zbyt przyjemnego sposobu na "super": musisz ręcznie określić metodę klas nadrzędnych, którą chcesz wywołać. W rezultacie istnieje wiele narzędzi ułatwiających tworzenie zajęć. Spróbuj spojrzeć na Prototype.js, Backbone.js lub podobną bibliotekę, która zawiera ładniejszą składnię do wykonywania OOP w js.
źródło
Ponieważ jest to najpopularniejszy hit w Google, chciałbym udzielić zaktualizowanej odpowiedzi.
Używanie klas ES6 znacznie ułatwia dziedziczenie i zastępowanie metod:
'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
Słowo
super
kluczowe odnosi się do klasy nadrzędnej, gdy jest używane w klasie dziedziczącej. Ponadto wszystkie metody w klasie nadrzędnej są powiązane z instancją dziecka, więc nie musisz pisaćsuper.method.apply(this);
.Jeśli chodzi o kompatybilność: tabela kompatybilności ES6 pokazuje tylko najnowsze wersje klas wsparcia głównych graczy (głównie). Przeglądarki V8 mają je od stycznia tego roku (Chrome i Opera), a Firefox, korzystający z silnika SpiderMonkey JS, doczeka się zajęć w przyszłym miesiącu z oficjalnym wydaniem Firefoksa 45. Po stronie mobilnej Android nadal nie obsługuje tej funkcji, podczas gdy iOS 9, wydany pięć miesięcy temu, ma częściową obsługę.
Na szczęście istnieje Babel , biblioteka JS do ponownej kompilacji kodu Harmony do kodu ES5. Klasy i wiele innych fajnych funkcji w ES6 może sprawić, że kod Javascript będzie dużo bardziej czytelny i łatwiejszy w utrzymaniu.
źródło
Kiedyś należy unikać emulacji klasycznego OO i zamiast tego używać prototypowego OO. Ładną biblioteką narzędzi dla prototypowych obiektów obiektowych są cechy .
Zamiast nadpisywać metody i konfigurować łańcuchy dziedziczenia (zawsze należy przedkładać kompozycję obiektu nad dziedziczenie obiektów), powinieneś łączyć funkcje wielokrotnego użytku w cechy i tworzyć z nimi obiekty.
Przykład na żywo
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);
źródło
modified () w twoim przykładzie to funkcja prywatna, która nie będzie dostępna z dowolnego miejsca poza definicją A, B lub C. Musisz to zadeklarować jako
this.modify = function(){}
C nie ma odniesienia do swoich rodziców, chyba że przekażesz je do C. Jeśli C jest skonfigurowane do dziedziczenia z A lub B, odziedziczy swoje metody publiczne (a nie swoje funkcje prywatne, takie jak zdefiniowano modyfikację ()). Gdy C odziedziczy metody od swojego rodzica, możesz zastąpić odziedziczone metody.
źródło
metoda
modify()
, którą wywołałeś w poprzednim, jest wywoływana w kontekście globalnym, jeśli chcesz nadpisać,modify()
musisz najpierw dziedziczyćA
lubB
.Może próbujesz to zrobić:
W tym przypadku
C
dziedziczyA
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();
źródło
C.prototype.modify()
miałby niewłaściwąthis
wartość. MianowicieC.prototype
zamiast przypadku c. Proszę użyć,.call(this)
ale wtedy twoja odpowiedź jest tylko duplikatem :)Nie, chyba że uczynisz wszystkie zmienne „publicznymi”, tj. Uczynisz je członkami
Function
albo bezpośrednio, albo przezprototype
właściwość.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( ) ;
Zauważysz kilka zmian.
Co najważniejsze, wywołanie rzekomego konstruktora „superklas” jest teraz niejawne w tym wierszu:
<name>.prototype = new C ;
Zarówno
A
iB
będzie teraz mieć indywidualnie modyfikowalnych członkówx
iy
które nie byłoby w przypadku, gdyby pisaliśmy... = C
zamiast.Następnie
x
,y
imodify
wszystkie są „publiczne” Członkowie tak że przypisywanie innymFunction
do nich<name>.prototype.modify = function( ) { /* ... */ }
zastąpi oryginał
Function
tą nazwą.Wreszcie, wywołanie do
modify
nie może być wykonane wFunction
deklaracji, ponieważ niejawne wywołanie „superklasy” byłoby następnie wykonane ponownie, gdy przypuszczaliśmy „superklasę” naprototype
własność rzekomej „podklasy”.Ale cóż, tak mniej więcej można to zrobić w JavaScript.
HTH,
FK
źródło
<name>.prototype = new C;
swoim shadowing wszystkich członków prototypu w każdym razieObjects
będzie współużytkować tego samego członka,C
jeśli nie utworzysz wystąpieniaC
obiektu. W ten sposób zmieniax
sięA
zmienix
wC
, a tym samym zmianyx
wB
. Co jest oczywiście niepożądane.A
iB
dziedziczymy poC
. Gdyby brakowało tej linii, nie byłoby to prawdą. W rzeczywistości jedynym prototypem, do którego w takim przypadku miałby dostęp zarówno „cień”,A
jak iB
„cień” byłbyObject.prototype
.x
,y
amodify
, a tym samym cień wszystkichC
członków tych. Jaki jest sens umieszczania C w prototypie, jeśli go nie używasz? To martwy kod.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();
źródło