1
0
Fork 0

AbstractClass.implement().extend() will now properly preserve abstract flag on resulting class

- This is a bug fix. The resulting class was not declared abstract, which is a problem if the resulting class chose not to provide a concrete implementation for each of the abstract members.
perfodd
Mike Gerwitz 2011-12-20 20:06:38 -05:00
parent 2136ebedd5
commit e9cf630d0b
2 changed files with 33 additions and 3 deletions

View File

@ -107,11 +107,19 @@ function markAbstract( args )
* *
* @param {Object} obj object to override * @param {Object} obj object to override
* *
* @return {undefined} * @return {Object} obj
*/ */
function abstractOverride( obj ) function abstractOverride( obj )
{ {
var extend = obj.extend; var extend = obj.extend,
impl = obj.implement;
// wrap and apply the abstract flag, only if the method is defined (it may
// not be under all circumstances, e.g. after an implement())
impl && ( obj.implement = function()
{
return abstractOverride( impl.apply( this, arguments ) );
} );
// wrap extend, applying the abstract flag // wrap extend, applying the abstract flag
obj.extend = function() obj.extend = function()
@ -119,5 +127,7 @@ function abstractOverride( obj )
markAbstract( arguments ); markAbstract( arguments );
return extend.apply( this, arguments ); return extend.apply( this, arguments );
}; };
return obj;
} }

View File

@ -26,7 +26,8 @@ var common = require( './common' ),
util = common.require( 'util' ), util = common.require( 'util' ),
Class = common.require( 'class' ), Class = common.require( 'class' ),
AbstractClass = common.require( 'class_abstract' ) AbstractClass = common.require( 'class_abstract' ),
Interface = common.require( 'interface' )
; ;
@ -451,3 +452,22 @@ var ConcreteFoo = Class.extend( AbstractFoo,
); );
} )(); } )();
/**
* Extending an abstract class after an implement() should still result in an
* abstract class. Essentially, we are testing to ensure that the extend()
* method is properly wrapped to flag the resulting class as abstract. This was
* a bug.
*/
( function testImplementingInterfacesWillPreserveAbstractClassDeclaration()
{
assert.doesNotThrow( function()
{
// if not considered abstract, extend() will fail, as it will contain
// abstract member foo
AbstractClass( 'TestImplExtend' )
.implement( Interface( { foo: [] } ) )
.extend( {} );
}, Error, 'Class should still be abstract after implement().extend()' );
} )()