From e26d7971ced3c89446d4d8a57d5391d2cd73bc75 Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Sun, 14 Nov 2010 22:03:55 -0500 Subject: [PATCH] Refactored abstract method logic --- lib/class.js | 90 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 36 deletions(-) diff --git a/lib/class.js b/lib/class.js index 59374ff..58c99d3 100644 --- a/lib/class.js +++ b/lib/class.js @@ -124,38 +124,6 @@ function prop_copy( props, dest, result_data ) getter = ( ( getset ) ? props.__lookupGetter__( 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 if ( getter || setter ) { @@ -172,11 +140,32 @@ function prop_copy( props, dest, result_data ) // check for method overrides 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 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; } } @@ -195,12 +184,18 @@ function prop_copy( props, dest, result_data ) * * The given method must be a function or an exception will be thrown. * - * @param {Function} super_method method to override - * @param {Function} new_method method to override with + * @param {Function} super_method method to override + * @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 */ -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 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" ); } + // 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 // method is called, so note that in the context of this // function, `this` will represent the current class instance