Digamos que tiene el siguiente código:
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));
}
Ahora la pregunta es, si hay alguna manera en la que puedo reemplazar el método modifyde Clos métodos que se encuentran en Ay B. En Java, usaría la superpalabra clave, pero ¿cómo puede lograr algo como esto en JavaScript?
javascript
oop
overriding
Daniel Nastase
fuente
fuente

modifyno es un método, sino una función anidada; hay una diferencia entre esos dos ...superpalabra clave para acceder a los campos y métodos no privados de una superclase. No lo usa para anularlos.Respuestas:
Editar: ¡Han pasado seis años desde que se escribió la respuesta original y muchas cosas han cambiado!
¡Buena suerte!
La herencia de JavaScript se ve un poco diferente a la de Java. Así es como se ve el sistema de objetos de 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"Desafortunadamente, esto es un poco feo y no incluye una forma muy agradable de "super": tienes que especificar manualmente el método de las clases principales que quieres llamar. Como resultado, hay una variedad de herramientas para hacer que la creación de clases sea más agradable. Intente buscar en Prototype.js, Backbone.js o una biblioteca similar que incluya una sintaxis más agradable para hacer OOP en js.
fuente
Dado que este es un gran éxito en Google, me gustaría dar una respuesta actualizada.
El uso de clases de ES6 hace que la herencia y la anulación de métodos sea mucho más fácil:
'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 BLa
superpalabra clave se refiere a la clase principal cuando se usa en la clase heredada. Además, todos los métodos de la clase principal están vinculados a la instancia del niño, por lo que no tiene que escribirsuper.method.apply(this);.En cuanto a la compatibilidad: la tabla de compatibilidad de ES6 muestra solo las versiones más recientes de las clases de soporte de los principales jugadores (en su mayoría). Los navegadores V8 los han tenido desde enero de este año (Chrome y Opera), y Firefox, usando el motor SpiderMonkey JS, verá clases el próximo mes con su lanzamiento oficial de Firefox 45. En el lado móvil, Android aún no es compatible con esta función, mientras que iOS 9, lanzado hace cinco meses, tiene soporte parcial.
Afortunadamente, existe Babel , una biblioteca JS para recompilar código Harmony en código ES5. Las clases y muchas otras características interesantes de ES6 pueden hacer que su código Javascript sea mucho más legible y fácil de mantener.
fuente
Once debería evitar emular OO clásico y usar OO prototípico en su lugar. Una buena biblioteca de utilidades para OO prototípicos son los rasgos .
En lugar de sobrescribir métodos y configurar cadenas de herencia (siempre se debe favorecer la composición de objetos sobre la herencia de objetos), debe agrupar funciones reutilizables en rasgos y crear objetos con ellos.
Ejemplo en 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);fuente
En su ejemplo, modificar () es una función privada, a la que no se podrá acceder desde ningún lugar excepto dentro de su definición A, B o C. Debería declararlo como
this.modify = function(){}C no tiene ninguna referencia a sus padres, a menos que se lo pase a C. Si C está configurado para heredar de A o B, heredará sus métodos públicos (no sus funciones privadas como ha definido modified ()). Una vez que C hereda los métodos de su padre, puede anular los métodos heredados.
fuente
el método
modify()que llamó en el último se llama en contexto global si desea anularmodify()primero debe heredarAoB.Quizás estás intentando hacer esto:
En este caso
CheredaAfunction 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();fuente
C.prototype.modify()tendría elthisvalor incorrecto . Es decir, enC.prototypelugar de la instancia de c. Utilice,.call(this)pero su respuesta es solo un duplicado :)No, a menos que haga todas las variables "públicas", es decir, las haga miembros de
Functionlaprototypepropiedad directamente o mediante la propiedad.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( ) ;Notarás algunos cambios.
Lo más importante es que la llamada al constructor de supuestas "superclases" ahora está implícita dentro de esta línea:
<name>.prototype = new C ;Ambos
AyBahora tendrán miembros modificables individualmentexyylo que no sería el caso si hubiéramos escrito en su... = Clugar.Entonces,
x,yymodifyson todos los miembros "públicos" de manera que la asignación de una diferenteFunctiona ellos<name>.prototype.modify = function( ) { /* ... */ }"anulará" el original
Functioncon ese nombre.Por último, la llamada a
modifyno se puede hacer en laFunctiondeclaración porque la llamada implícita a la "superclase" se volvería a ejecutar cuando establezcamos la supuesta "superclase" en laprototypepropiedad de las supuestas "subclases".Pero bueno, así es más o menos cómo harías este tipo de cosas en JavaScript.
HTH,
FK
fuente
<name>.prototype = new C;todos modosObjectscompartirían el mismo miembroCsi no crea una instancia de unCobjeto. Por lo tanto, cambiarxenAcambiaríaxenCy, por lo tanto, cambiaríaxenB. Lo cual es obviamente indeseable.AyBheredarC. Si faltara esa línea, ese no sería el caso. De hecho, el único prototipo tantoA, así comoBsería "sombra" tendría acceso a que en ese caso seríaObject.prototype.x, por lo tanto, ensombrecen a todos los miembros. ¿Cuál es el punto de poner C en el prototipo si no lo estás usando? Es un código muerto.ymodifyCfunction 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();fuente