2012-01-05 8 views
6

me di cuenta de que cada tutorial sobre cómo hacer la herencia JavaScript hace esto:¿Cómo se hace la herencia en JavaScript sin compartir la misma instancia de la superclase entre todas las instancias de la subclase?

SubClass.prototype = new SuperClass(); 

Pero esto creará una única instancia de la superclase y compartirlo entre todas las instancias de la clase sub.

El problema es que me gustaría pasar argumentos al constructor de la superclase que se originan a partir de los argumentos pasados ​​a la subclase.

En Java esto se haría así:

class SubClass extends SuperClass { 
    public SubClass(String s) { 
    super(s); 
    } 
} 

He intentado hacer algo como esto:

function SubClass(args) { 
    this.constructor.prototype = new SuperClass(args); 
} 

Pero esto no va a funcionar. Entonces, ¿hay alguna manera de hacer esto en JavaScript?

+0

Realmente no está creando una "instancia". Estás creando otro objeto. – ThiefMaster

+1

Deje de resistir - empiece a disfrutar;) http://stackoverflow.com/questions/2800964/benefits-of-prototypal-herheritance-over-classical – c69

+0

Eso es lo que intento hacer c69, pero no tengo idea de cómo. – mtanti

Respuesta

2

Así es como siempre lo he hecho.

// Parent object 
function Thing(options) 
{ 
    //do stuff 
} 

Thing.prototype.someMethod = function(){ 
    // some stuff 
    console.log('hello'); 
} 

// child object which inherits from the parent 
function OtherThing(options) 
{  
    Thing.call(this, options); 
    // do stuff for otherthing 
} 

OtherThing.prototype = new Thing(); 

OtherThing.prototype.someMethod = function(){ 
    // call things original function 
    Thing.prototype.someMethod.call(this); 

    // now do anything different 
    console.log('other thing says hi'); 
} 


var testObj = new OtherThing(); 
    testObj.someMethod(); 

Live Demo

1

Pero esto creará una sola instancia de la superclase y la compartirá entre todas las instancias de la subclase.

Sí, así es como funciona la herencia en JavaScript.

¿Hay alguna forma de hacer esto en JavaScript?

No sin horriblemente subvertir/torcer/mal usar el paradigma existente. Recomiendo tomar un enfoque diferente para implementar lo que sea que pretendas.

+0

¿Pero hay alguna manera de evitar reescribir el código para inicializar las variables en la superclase cada vez que escribo una nueva subclase? ¿Qué pasa si escribo sub sub clases? ¿Tendré que inicializar todas las variables de todos los antepasados? – mtanti

+0

En lugar de variables en la superclase, parece que debería usar _funciones_ que la subclase puede llamar. Quizás incluso permita una versión no-arg (que usaría la superclase) y una versión> 0-arg que usarían las subclases. –

5

Un patrón común es el siguiente: se crea

Un constructor temporal, que hereda de prototipo del constructor de los padres. El prototipo del constructor hijo se establece en una instancia del constructor temporal.

function inherits(Child, Parent) { 
    var Tmp = function() {}; 
    Tmp.prototype = Parent.prototype; 
    Child.prototype = new Tmp(); 
    Child.prototype.constructor = Child; 
} 

dentro del constructor del niño y luego tienes que llamar al constructor del antecesor:

function Child(a, b, c) { 
    Parent.call(this, a, b); 
} 

inherits(Child, Parent); 

// add prototype properties here 

Dentro de esta llamada de función, this hará referencia al nuevo objeto que se crea cuando se llama new Child(), por lo tanto, cualquiera que sea la inicialización se realiza dentro de Parent, se aplica al nuevo objeto que pasamos.

+0

No entiendo por qué es necesaria la función "heredar". ¿Por qué no hacer como sugiere http://stackoverflow.com/a/8736207/652460 y hacer todo de la manera habitual, excepto por el uso de la línea "Parent.call (this, args)"? Sé que he pedido una forma de crear nuevas instancias, pero de lo que estoy recopilando, el estado de la instancia de la clase padre será diferente para diferentes instancias de la subclase. – mtanti

+1

No entiendo tu última oración. Pero de todos modos, hacer algo como 'Child.prototype = new Parent()' funciona siempre que 'Parent' no espere (requiera) ningún argumento. Además, hace que el código sea un OMI un poco más limpio/más claro, pero eso podría ser subjetivo. Las principales bibliotecas como Google Closure Library y YUI proporcionan dicha función. –

+0

@mtanti Me preguntaba si. Sin el constructor temporal (Tmp) terminará llamando al constructor padre dos veces: Child.prototype = new Parent(), función Child (a, b, c) {Parent.call (this, a, b);}, y en la primera instancia, no tendrá parámetros para pasar al constructor padre. –

0

Otra forma sería deshacerse de la herencia de clase (pero no basada en clases) que implica el uso de constructor.

Utilice Object.create junto con Object.defineProperties. Esto se basa en el sistema de herencia nativo basado en prototipos que JavaScript sigue internamente.

Puede encontrar más información sobre las especificaciones de MDN y ECMAScript.

Sin embargo, estos métodos solo funcionan en los navegadores compatibles con ECMAScript 5. Esto excluye IE8 y anteriores. Afortunadamente, IE9 lo admite y al igual que el resto de los principales navegadores. A largo plazo, creo que este sería el camino a seguir.

Cuestiones relacionadas