开发者

Javascript: Allowing "virtual" function in base class to create instance of subclass

I have the following object model I want to get working - have been banging my head against the clone bit! Is this poss开发者_如何学Cible? I can't seem to get access to the SubClass constructor from within the baseclass without hard coding it.

The code is for a queue of arbitrary operations that all share a lot of common functionality; new operations are created as subclasses that merely override the action() method for operation specific functionality.

Is this possible without overriding the clone() method in each subclass?

/*
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 
  ...
}


To get access in your .clone() method to the constructor without having to hard-code it, a usual solution is to use the .constructor property which each object can set on its own prototype. The leaf object definition, will then have the override on the constructor property and will be the desired constructor to call. As you already seem to know, cloning an object with this method requires some knowledge about arguments that must be sent to the constructor.

This example here uses no arguments for the constructor. It then asks each object to support a .init method that accepts the object it was being cloned from so each class is then responsible for initializing the new clone from the original.

Here's an example in a running snippet:

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);
}

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜