2013-03-05 51 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)." : ".")); 
    } 
}