1
0
Fork 0

Added support for mixing in traits using use method on a base class

perfodd
Mike Gerwitz 2014-02-10 23:11:34 -05:00
parent 999c10c3bf
commit 897a4afab4
2 changed files with 65 additions and 4 deletions

View File

@ -374,9 +374,9 @@ function createUse( base, traits )
return { return {
extend: function() extend: function()
{ {
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 )
);
} );
}

View File

@ -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 );
},
} ); } );