Added support for mixing in traits using use method on a base class
parent
999c10c3bf
commit
897a4afab4
26
lib/class.js
26
lib/class.js
|
@ -376,7 +376,7 @@ function createUse( base, traits )
|
||||||
{
|
{
|
||||||
var args = Array.prototype.slice.call( arguments ),
|
var args = Array.prototype.slice.call( arguments ),
|
||||||
dfn = args.pop(),
|
dfn = args.pop(),
|
||||||
base = args.pop();
|
ext_base = args.pop();
|
||||||
|
|
||||||
// "mix" each trait into the provided definition object
|
// "mix" each trait into the provided definition object
|
||||||
for ( var i = 0, n = traits.length; i < n; i++ )
|
for ( var i = 0, n = traits.length; i < n; i++ )
|
||||||
|
@ -384,7 +384,7 @@ function createUse( base, traits )
|
||||||
traits[ i ].__mixin( dfn );
|
traits[ i ].__mixin( dfn );
|
||||||
}
|
}
|
||||||
|
|
||||||
var C = extend.call( null, base, dfn ),
|
var C = extend.call( null, ( base || ext_base ), dfn ),
|
||||||
meta = ClassBuilder.getMeta( C );
|
meta = ClassBuilder.getMeta( C );
|
||||||
|
|
||||||
// add each trait to the list of implemented types so that the
|
// add each trait to the list of implemented types so that the
|
||||||
|
@ -495,6 +495,7 @@ function setupProps( func )
|
||||||
{
|
{
|
||||||
attachExtend( func );
|
attachExtend( func );
|
||||||
attachImplement( func );
|
attachImplement( func );
|
||||||
|
attachUse( func );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -544,3 +545,24 @@ function attachImplement( func )
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attaches use method to the given function (class)
|
||||||
|
*
|
||||||
|
* Please see the `use' export of this module for more information.
|
||||||
|
*
|
||||||
|
* @param {function()} func function (class) to attach method to
|
||||||
|
*
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
function attachUse( func )
|
||||||
|
{
|
||||||
|
util.defineSecureProp( func, 'use', function()
|
||||||
|
{
|
||||||
|
return createUse(
|
||||||
|
func,
|
||||||
|
Array.prototype.slice.call( arguments )
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,4 +136,43 @@ require( 'common' ).testCase(
|
||||||
// o mixes in Tb
|
// o mixes in Tb
|
||||||
this.assertOk( this.Class.isA( Tb, o ) );
|
this.assertOk( this.Class.isA( Tb, o ) );
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This alternative syntax mixes a trait directly into a base class and
|
||||||
|
* then omits the base class as an argument to the extend method; this
|
||||||
|
* syntax is most familiar with named classes, but we are not testing
|
||||||
|
* named classes here.
|
||||||
|
*/
|
||||||
|
'Can mix in traits directly atop of existing class': function()
|
||||||
|
{
|
||||||
|
var called_foo = false,
|
||||||
|
called_bar = false,
|
||||||
|
called_baz = false;
|
||||||
|
|
||||||
|
var C = this.Class(
|
||||||
|
{
|
||||||
|
'public foo': function() { called_foo = true; },
|
||||||
|
} );
|
||||||
|
|
||||||
|
var T = this.Sut(
|
||||||
|
{
|
||||||
|
'public bar': function() { called_bar = true; },
|
||||||
|
} );
|
||||||
|
|
||||||
|
// we must ensure not only that we have mixed in the trait, but that
|
||||||
|
// we have also maintained C's interface and can further extend it
|
||||||
|
var inst = C.use( T ).extend(
|
||||||
|
{
|
||||||
|
'public baz': function() { called_baz = true; },
|
||||||
|
} )();
|
||||||
|
|
||||||
|
inst.foo();
|
||||||
|
inst.bar();
|
||||||
|
inst.baz();
|
||||||
|
|
||||||
|
this.assertOk( called_foo );
|
||||||
|
this.assertOk( called_bar );
|
||||||
|
this.assertOk( called_baz );
|
||||||
|
},
|
||||||
} );
|
} );
|
||||||
|
|
Loading…
Reference in New Issue