2013-03-05 48 views
6

我有一种每次调用时都会记录消息的方法。我希望这个日志消息指出方法是直接调用还是在子类中使用super调用。确定是否使用超级调用的ActionScript方法

class DoerOfWork { 
    public function doWork():void { 
     var calledWithSuper:Boolean; 

     calledWithSuper = ???; 

     trace("doWork called" + (calledWithSuper ? " (with super)." : ".")); 
    } 
} 

class SlowerDoerOfWork extends DoerOfWork { 
    public override function doWork():void { 
     for (var i:Number = 0; i < 321684; i++) { 
      // wait a moment 
     } 
     super.doWork(); 
    } 
} 

我希望这将是可以确定类this是否已经通过比较this.doWorkDoerOfWork.prototype.doWork覆盖的doWork实施。

不幸的是,这是不可能的。未绑定的方法在ActionScript中无法访问(规范列出了两种类型的函数:函数闭包和绑定方法)。在MethodClosure上的实例上甚至没有任何属性可以确定是否有两个绑定了相同方法的副本。

如何检查方法是否被重写或使用其他方法来确定当前正在执行的ActionScript方法是使用super调用还是直接调用?

回答

3

您可以获得对当前正在执行的函数的引用,如arguments.callee。从该方法,这将是MethodClosureDoerOfWork().doWork()this。如果doWork()未被覆盖,则将等于this.doWork

class DoerOfWork { 
    public function doWork():void { 
     var calledWithSuper:Boolean; 

     calledWithSuper = this.doWork == arguments.callee; 

     trace("doWork called" + (calledWithSuper ? " (with super)." : ".")); 
    } 
} 

如果您在非严格模式下运行,显然这将禁用当前函数的参数计数检查。 (我还没有这样检查自己,我什至不知道如何的IntelliJ禁用严格模式)

3

如果你愿意使用flash.utils.describeType(),它包含了我们需要的信息:

<type name="Main.as$1::SlowerDoerOfWork" base="Main.as$1::DoerOfWork" 
     isDynamic="false" isFinal="false" isStatic="false"> 
    <extendsClass type="Main.as$1::DoerOfWork"/> 
    <extendsClass type="Object"/> 
    <method name="doWork" declaredBy="Main.as$1::SlowerDoerOfWork" 
      returnType="void"> 
    <metadata name="__go_to_definition_help"> 
     <arg key="pos" value="1170"/> 
    </metadata> 
    </method> 
    <metadata name="__go_to_definition_help"> 
    <arg key="pos" value="1103"/> 
    </metadata> 
</type> 

XML中每个<method>declaredBy属性使用与flash.utils.getQualifiedClassName相同的格式,我们可以比较这些属性以确定我们的实现是否被覆盖。

class DoerOfWork { 
    public function doWork():void { 
     var calledWithSuper:Boolean; 

     var currentImplementationFrom:String 
      = flash.utils.describeType(this).method.(@name=="doWork")[email protected]; 
     var thisImplementationFrom:String 
      = flash.utils.getQualifiedClassName(DoerOfWork); 

     calledWithSuper = currentImplementationFrom != thisImplementationFrom; 

     trace("doWork called" + (calledWithSuper ? " (with super)." : ".")); 
    } 
}