3

Я хотел бы реализовать многоуровневое наследование, поддерживающее полиморфизм, реализованный метод расширения, выполняемый на расширяемом объекте (не по внешней утилите или функции - с точки зрения расширяемого объекта).Многоуровневый полиморфизм в javascript, полиморфный Object.extend

Т.Л., др jsfiddle здесь: 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 бы отменить метод, но это не так, потому что вар OBJS = [это, objectToBeMerged] оценивает это только MyObj, но хотелось бы, чтобы он оценивали на любой объект, на котором простираются выполняется (так в случае выполнения ActionObj.extend, я хотел бы иметь ключевое слово это в функция расширения оценивается в ActionObj, не MyObj)

Решение этой проблемы может использовать _.exten d из jQuery.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 выражения?

ответ

0

Я нашел решение, основываясь на underscode и магистральных источников (в частности, метод расширения магистралей применяется к каждому классу)

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

Как вы можете видеть, вычисляемая это работает, как ожидалось в polymoprhism! это можно улучшить, используя Backbone.extend функция