javascript中的多级多态,多态Object.extend

时间:2014-07-09 15:07:35

标签: javascript inheritance polymorphism parametric-polymorphism

我希望实现多级继承,支持由在对象扩展上执行的扩展方法实现的多态性(不是通过外部实用程序或函数 - 从扩展对象的角度来看)。

tl; dr jsfiddle here http://jsfiddle.net/arzo/VLkF7/

我想要什么?

var MyObj = {name: 'object', toString: function() {return this.name;}};
MyObj.extend = function(objectToBeMerged) {
    var objs=[this, objectToBeMerged],
        newobj={},
        obj;
    for(var i in objs) {
            for(var k in (obj=objs[i]) ) if (obj.hasOwnProperty(k)) newobj[k]=obj[k];
    }
    return newobj;
}
console.assert(MyObj.extend, 'ERROR: this should pass');
var ActionObj = MyObj.extend({name: 'action abstract object', exec: 'implemtation', undo: 'implementation of opposite action here'});

var DragNDrop = ActionObj.extend({name: 'drag&drop action', exec: function(){console.log('did d&d');}})
//unfortunately following assert will not get through, because MyObj.extend cannot iterate over ActionObj properties
if(DragNDrop.toString) console.info('MyObj.extend iterated over MyObj\'s properties')
console.assert(DragNDrop.undo, 'but MyObj.extend did not iterate over ActionObj properties, undo action is missing in this object:', DragNDrop)
;

上面的代码有什么问题?如果这是常规的,例如C ++继承,然后DragNDrop将有撤消方法,但它没有,因为 var objs = [this,objectToBeMerged] 仅将此评估为 MyObj ,但我想让它评估到执行扩展的任何对象(因此,在执行ActionObj.extend的情况下,我希望在<的情况下使用 this em> function extends 评估为 ActionObj ,而非 MyObj

解决这个问题的方法可能是使用jQuery.extend的_.extend,它看起来像:

//add here code in previous quote in this post...
MyUtils = {}
MyUtils.extend = function(objectToBeMerged, parent) {
    var objs=[parent || this, objectToBeMerged],
        newobj={},
        obj;
    for(var i in objs) {
            for(var k in (obj=objs[i]) ) if (obj.hasOwnProperty(k)) newobj[k]=obj[k];
    }
    return newobj;
}
console.assert(MyObj && ActionObj, 'are you sure you have added code from previous block?');
var DnDAction=MyUtils.extend({name: 'drag&drop action', exec: function(){console.log('did d&d');}},ActionObj);
if (DnDAction.undo) console.info('using MyUtils.extend works fine and .undo is defined as expected in', DnDAction)
;

但上面的解决方案需要使用外部工具 - 在这种情况下MyUtils,这不是真正的多态解决方案

您是否知道如何强制MyObj.extend迭代运行时评估(不是在定义评估时)this表达式?

1 个答案:

答案 0 :(得分:0)

我找到了解决方案,基于底层代码和主干源(特别是适用于每个类的Backbones扩展方法)

var obj = {
  name: 'hi',
  getKeys: function() {
    var o=[];
    try{
      o=Array.prototype.slice.apply(this,0); //in case browser's engine is fckd up ....
    } catch (e) { //implementation feature of conerting to an array
      for(var i in this) o.push(i);
    }
    var _this=this;
    return o.map(function(i,e){return _this[i];});
  },
};

var obj2 = {
  __proto__: obj,
  extension: 'impl.',
  name: 'great hi'
};

var obj3 = {
  __proto__: obj2,
  extension: 'impl2.',
  name: 'greater hi'
};

console.assert(obj.getKeys().length!=obj2.getKeys().length, 'something went wrong, they are not equal');
console.log(obj.getKeys(), obj2.getKeys(), obj3.getKeys());

正如您所看到的,对此进行评估的工作原理与多态性一样! 这可以通过使用Backbone.extend 功能

来改进