Digamos que você tenha o código abaixo:
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));
}
Agora a questão é, se há alguma maneira pela qual eu posso substituir o método modify
de C
com os métodos que estão em A
e B
. Em Java, você usaria a super
-palavra - chave, mas como você pode conseguir algo assim em JavaScript?
javascript
oop
overriding
Daniel Nastase
fonte
fonte
modify
não é um método, mas uma função aninhada - há uma diferença entre os dois ...super
palavra-chave para acessar os campos e métodos não privados de uma superclasse. Você não o usa para substituí-los.Respostas:
Edit: Já se passaram seis anos desde que a resposta original foi escrita e muita coisa mudou!
Boa sorte!
A herança do JavaScript parece um pouco diferente do Java. Esta é a aparência do sistema de objeto JavaScript nativo:
// 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"
Infelizmente, isso é um pouco feio e não inclui uma maneira muito boa de "super": você deve especificar manualmente o método das classes pai que deseja chamar. Como resultado, há uma variedade de ferramentas para tornar a criação de classes mais agradável. Tente examinar Prototype.js, Backbone.js ou uma biblioteca semelhante que inclua uma sintaxe mais agradável para fazer OOP em js.
fonte
Como este é um dos principais sucessos do Google, gostaria de dar uma resposta atualizada.
O uso de classes ES6 torna a herança e a substituição de métodos muito mais fáceis:
'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
A
super
palavra-chave refere-se à classe pai quando usada na classe herdada. Além disso, todos os métodos da classe pai são vinculados à instância do filho, portanto, você não precisa escreversuper.method.apply(this);
.Quanto à compatibilidade: a tabela de compatibilidade ES6 mostra apenas as versões mais recentes das classes de suporte dos principais players (principalmente). Os navegadores V8 os têm desde janeiro deste ano (Chrome e Opera), e o Firefox, usando o mecanismo SpiderMonkey JS, terá aulas no próximo mês com o lançamento oficial do Firefox 45. No lado móvel, o Android ainda não oferece suporte a esse recurso, enquanto o iOS 9, lançado há cinco meses, tem suporte parcial.
Felizmente, existe a Babel , uma biblioteca JS para recompilar o código Harmony em código ES5. Classes e muitos outros recursos interessantes no ES6 podem tornar seu código Javascript muito mais legível e sustentável.
fonte
O Once deve evitar emular OO clássico e usar OO prototípico. Uma boa biblioteca de utilitários para OO prototípico é traits .
Em vez de sobrescrever métodos e configurar cadeias de herança (deve-se sempre favorecer a composição de objetos em vez da herança de objetos), você deve agrupar funções reutilizáveis em características e criar objetos com elas.
Exemplo ao Vivo
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);
fonte
modify () em seu exemplo é uma função privada, que não estará acessível de qualquer lugar, exceto dentro de sua definição A, B ou C. Você precisaria declará-lo como
this.modify = function(){}
C não tem referência a seus pais, a menos que você o passe para C. Se C for configurado para herdar de A ou B, ele herdará seus métodos públicos (não suas funções privadas, como você definiu modify ()). Depois que C herda os métodos de seu pai, você pode substituir os métodos herdados.
fonte
o método
modify()
que você chamou por último é chamado no contexto global se você deseja substituir,modify()
primeiro precisa herdarA
ouB
.Talvez você esteja tentando fazer isso:
Neste caso
C
herdaA
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();
fonte
C.prototype.modify()
teria othis
valor errado . Ou seja, emC.prototype
vez da instância de c. Por favor, use,.call(this)
mas então sua resposta é apenas uma duplicata :)A não ser que você torne todas as variáveis "públicas", isto é, torne-as membros do
Function
diretamente ou por meio daprototype
propriedade.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( ) ;
Você notará algumas mudanças.
Mais importante ainda, a chamada ao suposto construtor de "superclasses" agora está implícita nesta linha:
<name>.prototype = new C ;
Ambos
A
eB
agora terão membros modificáveis individualmentex
ey
que não seria o caso se tivéssemos escrito em... = C
vez disso.Em seguida,
x
,y
emodify
são todos os membros "públicas" de modo a que a atribuição de um diferenteFunction
para eles<name>.prototype.modify = function( ) { /* ... */ }
irá "substituir" o original
Function
com esse nome.Por último, a chamada para
modify
não pode ser feita naFunction
declaração porque a chamada implícita para a "superclasse" seria então executada novamente quando configurássemos a suposta "superclasse" para aprototype
propriedade das supostas "subclasses".Mas bem, é mais ou menos assim que você faria esse tipo de coisa em JavaScript.
HTH,
FK
fonte
<name>.prototype = new C;
você seguir todos os membros do protótipoObjects
estaria compartilhando o mesmo membro emC
se você não instanciar umC
objeto. Assim, mudarx
emA
mudariax
emC
e, portanto, mudariax
emB
. O que é obviamente indesejável.A
eB
herdar deC
. Se essa linha estivesse faltando, não seria o caso. Na verdade, o único protótipoA
ao qualB
"sombra" teria acesso nesse caso seriaObject.prototype
.x
, portanto, sombreiam todos os membros de. Qual é o ponto de colocar C no protótipo se você não o estiver usando? É um código morto.y
modify
C
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();
fonte