views:

173

answers:

2

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?

A: 

If you are asking inside the same object you can

overriden = (this[stringNameOfMethod] instanceOf Function && super[stringNameOfMethod] instanceOf Function);

If not, try using describeType. Check if there's a method with the name and check the "declaredBy" attribute. Voila!

http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/utils/package.html#describeType()

Sorry, I'm in the middle of a migration from CS3 to Flash builder so for now I cannot ensure my ideas work correctly. But I will be back.

eipipuz
I tried that before, but please note that it does not matter if the class is a direct or indirect child of the base class Component.
Seth Illgard
+1  A: 

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
LopSae
Excellent, let me give it a try.
Seth Illgard
After reading again the context of the problem it came to me that the solution for your problem may be even simpler. If you are already sure of the hierarchy of your class (you know it extends your component class) you can just search in the type description for the methods you want, and if those are "@declaredBy" the same class, the that means they are overridden.
LopSae