1
0
Fork 0

Refactored abstract method logic

closure/master
Mike Gerwitz 2010-11-14 22:03:55 -05:00
parent 52944c4207
commit e26d7971ce
1 changed files with 54 additions and 36 deletions

View File

@ -124,38 +124,6 @@ function prop_copy( props, dest, result_data )
getter = ( ( getset ) ? props.__lookupGetter__( property ) : null ), getter = ( ( getset ) ? props.__lookupGetter__( property ) : null ),
setter = ( ( getset ) ? props.__lookupSetter__( property ) : null ); setter = ( ( getset ) ? props.__lookupSetter__( property ) : null );
// did we find an abstract method?
if ( prop instanceof Function )
{
if ( prop.abstractFlag === true )
{
abstract_methods.push( property );
}
else
{
// if we were given a concrete method to an abstract method,
// then the method should no longer be considered abstract
if ( abstract_map[ property ] !== undefined )
{
if ( pre.definition )
{
// ensure the concrete definition is compatible with
// that of its supertype
if ( prop.length < pre.definition.length )
{
throw new Error(
"Declaration of " + property + " must be compatiable" +
"with that of its supertype"
);
}
}
delete abstract_methods[ abstract_map[ property ] ];
abstract_regen = true;
}
}
}
// check for getter/setter overrides // check for getter/setter overrides
if ( getter || setter ) if ( getter || setter )
{ {
@ -172,11 +140,32 @@ function prop_copy( props, dest, result_data )
// check for method overrides // check for method overrides
else if ( ( pre !== undefined ) && ( pre instanceof Function ) ) else if ( ( pre !== undefined ) && ( pre instanceof Function ) )
{ {
dest[ property ] = method_override( pre, prop ); var data = { abstractModified: false };
dest[ property ] = method_override(
pre,
prop,
property,
abstract_map,
abstract_methods,
data
);
if ( data.abstractModified )
{
abstract_regen = true;
}
} }
// just copy over the property // just copy over the property
else else
{ {
// if we were given an abstract method, add it to our list of
// abstract methods
if ( ( prop instanceof Function ) && ( prop.abstractFlag === true ) )
{
abstract_methods.push( property );
}
dest[ property ] = prop; dest[ property ] = prop;
} }
} }
@ -197,10 +186,16 @@ function prop_copy( props, dest, result_data )
* *
* @param {Function} super_method method to override * @param {Function} super_method method to override
* @param {Function} new_method method to override with * @param {Function} new_method method to override with
* @param {string} name method name
* @param {Object} abstract_map lookup table for abstract methods
* @param {Array} abstract_methods list of abstract methods
* @param {Object} data object in which to store result data
* *
* @return {Function} overridden method * @return {Function} overridden method
*/ */
function method_override( super_method, new_method ) function method_override(
super_method, new_method, name, abstract_map, abstract_methods, data
)
{ {
// ensure we're overriding the method with another method // ensure we're overriding the method with another method
if ( !( new_method instanceof Function ) ) if ( !( new_method instanceof Function ) )
@ -208,6 +203,29 @@ function method_override( super_method, new_method )
throw new TypeError( "Cannot override method with non-method" ); throw new TypeError( "Cannot override method with non-method" );
} }
// if we were given a concrete method to an abstract method,
// then the method should no longer be considered abstract
if ( ( abstract_map[ name ] !== undefined )
&& ( new_method.abstractFlag !== true )
)
{
if ( super_method.definition instanceof Function )
{
// ensure the concrete definition is compatible with
// that of its supertype
if ( new_method.length < super_method.definition.length )
{
throw new Error(
"Declaration of " + name + " must be compatiable" +
"with that of its supertype"
);
}
}
delete abstract_methods[ abstract_map[ name ] ];
data.abstractModified = true;
}
// this is the method that will be invoked when the requested // this is the method that will be invoked when the requested
// method is called, so note that in the context of this // method is called, so note that in the context of this
// function, `this` will represent the current class instance // function, `this` will represent the current class instance