R – AS3 reflection. How to find out if a method is overridden

actionscript-3reflection

Is it possible to use AS3 reflection to find out if a method was overridden?

I need a method like:

protected function isOverriden(methodName:string) : bool
{
    //magic here!
    //...

    return awesomeLocalVariable;
}

So, I pass in the method name as a string and the isOverridden method yields true only if and only if the object has a method of that name and it is overridden from its original implementation.

Any idea on how to code the magic there?

Thanks.

Edit: As requested, the context of the problem:

I'm building a framework for creating AS3 games. I want to provide "components" for my game objects, each component provides functionality to the game object it is applied. Components are based on events (onClick, onUpdate, onShapeCollision, etc) I need this code in the Component class, so I can register only the events that the actual Component-derived class implements (overrides).

Example component:

    public class CTrace extends ScriptComponent
    {
            public override function onClick(event:MouseEvent = null):void
            {
                    trace(Owner.Id);
            }
    }

The framework should register the onClick method as the event handler for the MouseEvent.CLICK event because it overrides the default implementation.

Why do I need the default implementation? Because I want the classes to override the supported methods so there will be a compile time error if the user tries to use an unsupported event.

Does that makes sense?

Best Answer

Here is a try. The function is static and it may be used to check any class or object regardless of the class in which it is implemented. If you give it the type, it will use it, if you give it an instance, it will get the type by itself. The inner logic is just to check the given type description for the function we are looking for, if such exists and is declared by the class, it will check if the method also exists in the parent. And if both exists, enjoy, it means it is overridden.

/**
 * Returns true only if the method name given is declared by
 * the source class, and any parent class.
 */
static public function isOverridden(source:*, methodName:String):Boolean {
    var parentTypeName:String = getQualifiedSuperclassName(source);
    if (parentTypeName == null) {
        return false;
    }//if

    var typeName:String = getQualifiedClassName(source);
    var typeDesc:XML = describeType(getDefinitionByName(typeName));
    var methodList:XMLList = typeDesc.factory.method.(@name == methodName);

    if (methodList.length() > 0) {
        //Method exists
        var methodData:XML = methodList[0];
        if (methodData.@declaredBy == typeName) {
            //Method is declared in self
            var parentTypeDesc:XML = describeType(getDefinitionByName(parentTypeName));
            var parentMethodList:XMLList = parentTypeDesc.factory.method.(@name == methodName);
            return parentMethodList.length() > 0;
        }//if
    }//if

    return false;
}//isOverridden

And just in case it is needed, the imports required for it to work:

import flash.utils.describeType;
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;
import flash.utils.getQualifiedSuperclassName;

And to use it:

trace(isOverridden(ChildrenClass, "overriddenMethod")); //true
trace(isOverridden(ChildrenClass, "onlyChildMethod")); //false
trace(isOverridden(ChildrenClass, "onlyParentMethod")); //false