diff --git a/lib/ClassBuilder.js b/lib/ClassBuilder.js index 2b02134..a9902d7 100644 --- a/lib/ClassBuilder.js +++ b/lib/ClassBuilder.js @@ -259,7 +259,8 @@ exports.isInstanceOf = function( type, instance ) implemented = meta.implemented; i = implemented.length; - // check implemented interfaces + // check implemented interfaces et. al. (other systems may make use of + // this meta-attribute to provide references to types) while ( i-- ) { if ( implemented[ i ] === type ) diff --git a/lib/class.js b/lib/class.js index 0a0cdfa..af2d51a 100644 --- a/lib/class.js +++ b/lib/class.js @@ -384,7 +384,17 @@ function createUse( base, traits ) traits[ i ].__mixin( dfn ); } - return extend.call( null, base, dfn ); + var C = extend.call( null, base, dfn ), + meta = ClassBuilder.getMeta( C ); + + // add each trait to the list of implemented types so that the + // class is considered to be of type T in traits + for ( var i = 0, n = traits.length; i < n; i++ ) + { + meta.implemented.push( traits[ i ] ); + } + + return C; }, }; } diff --git a/test/Trait/DefinitionTest.js b/test/Trait/DefinitionTest.js index cbaff31..c4b1b26 100644 --- a/test/Trait/DefinitionTest.js +++ b/test/Trait/DefinitionTest.js @@ -245,4 +245,26 @@ require( 'common' ).testCase( this.fail( false, true, "Mixin must fail on conflict: " + desc ); }, + + + /** + * Traits in ease.js were designed in such a way that an object can be + * considered to be a type of any of the traits that its class mixes in; + * this is consistent with the concept of interfaces and provides a very + * simple and intuitive type system. + */ + 'A class is considered to be a type of each used trait': function() + { + var Ta = this.Sut( {} ), + Tb = this.Sut( {} ), + Tc = this.Sut( {} ), + o = this.Class.use( Ta, Tb ).extend( {} )(); + + // these two were mixed in + this.assertOk( this.Class.isA( Ta, o ) ); + this.assertOk( this.Class.isA( Tb, o ) ); + + // this one was not + this.assertOk( this.Class.isA( Tc, o ) === false ); + }, } ); diff --git a/test/Trait/MixedExtendTest.js b/test/Trait/MixedExtendTest.js index 76f8cb6..80e44f7 100644 --- a/test/Trait/MixedExtendTest.js +++ b/test/Trait/MixedExtendTest.js @@ -56,4 +56,19 @@ require( 'common' ).testCase( C().foo(); this.assertOk( called ); }, + + + /** + * Just as subtypes inherit the same polymorphisms with respect to + * interfaces, so too should subtypes inherit supertypes' mixed in + * traits' types. + */ + 'Subtype has same polymorphic qualities of parent mixins': function() + { + var T = this.Sut( {} ), + o = this.Class.use( T ).extend( {} ).extend( {} )(); + + // o's supertype mixes in T + this.assertOk( this.Class.isA( T, o ) ); + }, } );