Added support for mixing in traits using use method on a base class
parent
999c10c3bf
commit
897a4afab4
30
lib/class.js
30
lib/class.js
|
@ -374,9 +374,9 @@ function createUse( base, traits )
|
|||
return {
|
||||
extend: function()
|
||||
{
|
||||
var args = Array.prototype.slice.call( arguments ),
|
||||
dfn = args.pop(),
|
||||
base = args.pop();
|
||||
var args = Array.prototype.slice.call( arguments ),
|
||||
dfn = args.pop(),
|
||||
ext_base = args.pop();
|
||||
|
||||
// "mix" each trait into the provided definition object
|
||||
for ( var i = 0, n = traits.length; i < n; i++ )
|
||||
|
@ -384,7 +384,7 @@ function createUse( base, traits )
|
|||
traits[ i ].__mixin( dfn );
|
||||
}
|
||||
|
||||
var C = extend.call( null, base, dfn ),
|
||||
var C = extend.call( null, ( base || ext_base ), dfn ),
|
||||
meta = ClassBuilder.getMeta( C );
|
||||
|
||||
// add each trait to the list of implemented types so that the
|
||||
|
@ -495,6 +495,7 @@ function setupProps( func )
|
|||
{
|
||||
attachExtend( 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
|
||||
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