2013-03-05 8 views
6

Mam metodę, która rejestruje komunikat przy każdym wywołaniu. Chciałbym, aby ten komunikat dziennika wskazał, czy metoda została wywołana bezpośrednio, czy wywołana przy użyciu klasy super w klasie potomnej.Określa, czy metoda ActionScript wywoływana przy użyciu super

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(); 
    } 
} 

Mam nadzieję, że będzie to możliwe do ustalenia, czy klasa this była przesłonięta realizację doWork porównując this.doWork do DoerOfWork.prototype.doWork.

Niestety nie jest to możliwe. Metody niezwiązane są niedostępne nigdzie w języku ActionScript (specyfikacja zawiera dwa typy funkcji: zamknięcia funkcji i metody związane). Nie ma nawet żadnych właściwości instancji na MethodClosure, które mogłyby zidentyfikować, czy dwa są związanymi kopiami tej samej metody.

Jak mogę sprawdzić, czy dana metoda została nadpisana lub użyć innej metody w celu ustalenia, czy aktualnie wykonywana metoda ActionScript została wywołana przy użyciu super lub bezpośrednio?

Odpowiedz

3

Możesz uzyskać odwołanie do aktualnie wykonywanej funkcji jako arguments.callee. Z metody będzie to MethodClosure z DoerOfWork().doWork() z this. Jeśli doWork() nie zostanie przesłonięty, będzie to równa this.doWork.

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

     calledWithSuper = this.doWork == arguments.callee; 

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

Jeśli używasz trybu nie-rygorystycznego, najwyraźniej spowoduje to wyłączenie sprawdzania liczby argumentów dla bieżącej funkcji. (. Nie sprawdzałem ten sam, nie jestem nawet pewien, jak wyłączyć tryb ścisły w IntelliJ)

3

Jeśli jesteś gotów użyć flash.utils.describeType(), zawiera informacje potrzebne:

<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> 

Atrybut declaredBy każdego z <method> w XML używa tego samego formatu co flash.utils.getQualifiedClassName, i możemy je porównać, aby ustalić, czy nasza implementacja została nadpisana.

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)." : ".")); 
    } 
}