2010-10-23 20 views
2

J'ai le modèle d'objet suivant que je veux travailler - je me suis cogné la tête contre le clone! Est-ce possible? Je n'arrive pas à accéder au constructeur SubClass à partir de la classe de base sans le coder en dur.Javascript: Permettre la fonction "virtuelle" dans la classe de base pour créer l'instance de la sous-classe

Le code est pour une file d'opérations arbitraires qui partagent toutes beaucoup de fonctionnalités communes; les nouvelles opérations sont créées en tant que sous-classes qui remplacent simplement la méthode action() pour une fonctionnalité spécifique à l'opération.

Est-ce possible sans surcharger la méthode clone() dans chaque sous-classe?

/* 
Application specific subclass: 
*/ 
function SubClass_Operation1() 
{ 
    BaseOperationClass.apply(this, arguments); // Call inherited constructor 

    this.action = function() 
    { 
    this.manager.addToQueue(this.clone({changeValue:1})); 
    this.manager.addToQueue(this.clone({changeValue:2})); 
    this.manager.addToQueue(this.clone({changeValue:3})); 
    } 
} 
SubClass.prototype = new BaseOperationClass; 

// More of these defined for each operation 
... 

/* 
Base class containing all common functionality 
*/ 
function BaseOperationClass(manager) 
{ 
    this.manager = manager; 

    // Placeholder for virtual action() function 
    this.action = function() 
    { 
    } 

    this.clone = function(mods) 
    { 
    var res = ?????? // Should create exact copy of current SubClass 

    res.applyModifications(mods); 
    } 

    this.applyModifications(mods) 
    { 
    ... 
    } 

    // Lots of common functionality 
    ... 
} 
+0

Je suis tombé sur ce problème (cherché et trouvé votre question) et compris une solution pour cela. Si vous avez encore des problèmes, faites le moi savoir et je vais écrire un exemple pour vous. –

+0

Simon, partagez, je suis sûr que ça va aider quelqu'un. –

+0

Comment pouvez-vous prédire avec précision quels seront les paramètres du constructeur de la classe de base? – jsmaupin

Répondre

0

Pour obtenir un accès dans votre méthode .clone() au constructeur sans avoir à coder en dur il, une solution habituelle consiste à utiliser la propriété .constructor que chaque objet peut mettre sur son propre prototype. La définition de l'objet feuille aura alors la priorité sur la propriété du constructeur et sera le constructeur à appeler. Comme vous le savez déjà, le clonage d'un objet avec cette méthode nécessite des connaissances sur les arguments qui doivent être envoyés au constructeur.

Cet exemple n'utilise aucun argument pour le constructeur. Il demande ensuite à chaque objet de prendre en charge une méthode .init qui accepte l'objet à partir duquel il a été cloné. Chaque classe est alors responsable de l'initialisation du nouveau clone à partir de l'original.

Voici un exemple dans un extrait en cours d'exécution:

function Base() { 
 
    this.type = "base"; 
 
} 
 

 
Base.prototype = { 
 
    clone: function() { 
 
     var c = new this.constructor(); 
 
     // let clone initialize itself from the original 
 
     c.init(this); 
 
     return c; 
 
    }, 
 
    setName: function(name) { 
 
     this.name = name; 
 
    }, 
 
    init: function(obj) { 
 
     // copy over name instance data 
 
     this.name = obj.name; 
 
    } 
 
} 
 

 
// set .constructor property for use with .clone() 
 
Base.prototype.constructor = Base; 
 

 
function Derived() { 
 
    Base.call(this); 
 
    this.type = "derived"; 
 
} 
 

 
// inherit from Base 
 
Derived.prototype = Object.create(Base.prototype); 
 
Derived.prototype.setOccupation = function(occupation) { 
 
    this.occupation = occupation; 
 
} 
 
Derived.prototype.init = function(obj) { 
 
    // let base object init itself 
 
    Base.prototype.init.call(this, obj); 
 
    
 
    // copy over our own instance data 
 
    this.occupation = obj.occupation; 
 
} 
 

 
// set .constructor property for use with .clone() 
 
Derived.prototype.constructor = Derived; 
 

 
var x = new Derived(); 
 
x.setName("Bob"); 
 
x.setOccupation("Engineer"); 
 
var xx = x.clone(); 
 

 
var y = new Base(); 
 
y.setName("Alice"); 
 
var yy = y.clone(); 
 

 
log(x !== xx) 
 
log(x); 
 
log(xx); 
 
log(y); 
 
log(yy) 
 

 
// function just for output in snippet 
 
function log(a) { 
 
    var div = document.createElement("div"); 
 
    if (typeof a === "object") { 
 
     a = JSON.stringify(a); 
 
    } 
 
    div.innerHTML = a; 
 
    document.body.appendChild(div); 
 
}