[ADD] method to extend classes in place (w/o reassignment)
semantics similar to ruby's Module.include bzr revid: xmo@openerp.com-20110808094030-qfmi2s14vqz2nybz
This commit is contained in:
parent
0056818c76
commit
2f94a513bd
|
@ -56,6 +56,35 @@ openerp.base.core = function(openerp) {
|
|||
}
|
||||
return this;
|
||||
}
|
||||
Class.mix = function (properties) {
|
||||
for (var name in properties) {
|
||||
if (typeof properties[name] !== 'function'
|
||||
|| !fnTest.test(properties[name])) {
|
||||
prototype[name] = properties[name];
|
||||
} else if (typeof prototype[name] === 'function'
|
||||
&& prototype.hasOwnProperty(name)) {
|
||||
prototype[name] = (function (name, fn, previous) {
|
||||
return function () {
|
||||
var tmp = this._super;
|
||||
this._super = previous;
|
||||
var ret = fn.apply(this, arguments);
|
||||
this._super = tmp;
|
||||
return ret;
|
||||
}
|
||||
})(name, properties[name], prototype[name]);
|
||||
} else if (typeof _super[name] === 'function') {
|
||||
prototype[name] = (function (name, fn) {
|
||||
return function () {
|
||||
var tmp = this._super;
|
||||
this._super = _super[name];
|
||||
var ret = fn.apply(this, arguments);
|
||||
this._super = tmp;
|
||||
return ret;
|
||||
}
|
||||
})(name, properties[name]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Populate our constructed prototype object
|
||||
Class.prototype = prototype;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
$(document).ready(function () {
|
||||
var openerp;
|
||||
module('Base Class', {
|
||||
module('base-class', {
|
||||
setup: function () {
|
||||
openerp = window.openerp.init();
|
||||
window.openerp.base.core(openerp);
|
||||
|
@ -12,11 +12,11 @@ $(document).ready(function () {
|
|||
return this.somevar;
|
||||
}
|
||||
});
|
||||
var i1 = new C();
|
||||
i1.somevar = 3;
|
||||
var instance = new C();
|
||||
instance.somevar = 3;
|
||||
|
||||
ok(i1 instanceof C);
|
||||
strictEqual(i1.foo(), 3);
|
||||
ok(instance instanceof C);
|
||||
strictEqual(instance.foo(), 3);
|
||||
});
|
||||
test('Class initialization', function () {
|
||||
var C1 = openerp.base.Class.extend({
|
||||
|
@ -57,4 +57,82 @@ $(document).ready(function () {
|
|||
strictEqual(new C1().foo(), 2);
|
||||
strictEqual(new C2().foo(), 3);
|
||||
});
|
||||
test('In-place extension', function () {
|
||||
var C0 = openerp.base.Class.extend({
|
||||
foo: function () {
|
||||
return 3;
|
||||
},
|
||||
qux: function () {
|
||||
return 3;
|
||||
},
|
||||
bar: 3
|
||||
});
|
||||
C0.mix({
|
||||
foo: function () {
|
||||
return 5;
|
||||
},
|
||||
qux: function () {
|
||||
return 2 + this._super();
|
||||
},
|
||||
bar: 5,
|
||||
baz: 5
|
||||
});
|
||||
|
||||
strictEqual(new C0().bar, 5);
|
||||
strictEqual(new C0().baz, 5);
|
||||
strictEqual(new C0().foo(), 5);
|
||||
strictEqual(new C0().qux(), 5);
|
||||
});
|
||||
test('In-place extension and inheritance', function () {
|
||||
var C0 = openerp.base.Class.extend({
|
||||
foo: function () { return 1; },
|
||||
bar: function () { return 1; }
|
||||
});
|
||||
var C1 = C0.extend({
|
||||
foo: function () { return 1 + this._super(); }
|
||||
});
|
||||
strictEqual(new C1().foo(), 2);
|
||||
strictEqual(new C1().bar(), 1);
|
||||
|
||||
C1.mix({
|
||||
foo: function () { return 2 + this._super(); },
|
||||
bar: function () { return 1 + this._super(); }
|
||||
});
|
||||
strictEqual(new C1().foo(), 4);
|
||||
strictEqual(new C1().bar(), 2);
|
||||
});
|
||||
test('In-place extensions alter existing instances', function () {
|
||||
var C0 = openerp.base.Class.extend({
|
||||
foo: function () { return 1; },
|
||||
bar: function () { return 1; }
|
||||
});
|
||||
var instance = new C0();
|
||||
strictEqual(instance.foo(), 1);
|
||||
strictEqual(instance.bar(), 1);
|
||||
|
||||
C0.mix({
|
||||
foo: function () { return 2; },
|
||||
bar: function () { return 2 + this._super(); }
|
||||
});
|
||||
strictEqual(instance.foo(), 2);
|
||||
strictEqual(instance.bar(), 3);
|
||||
});
|
||||
test('In-place extension of subclassed types', function () {
|
||||
var C0 = openerp.base.Class.extend({
|
||||
foo: function () { return 1; },
|
||||
bar: function () { return 1; }
|
||||
});
|
||||
var C1 = C0.extend({
|
||||
foo: function () { return 1 + this._super(); },
|
||||
bar: function () { return 1 + this._super(); }
|
||||
});
|
||||
var instance = new C1();
|
||||
strictEqual(instance.foo(), 2);
|
||||
C0.mix({
|
||||
foo: function () { return 2; },
|
||||
bar: function () { return 2 + this._super(); }
|
||||
});
|
||||
strictEqual(instance.foo(), 3);
|
||||
strictEqual(instance.bar(), 4);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue