6

我有一个方法,每次调用时都会记录一条消息。我希望此日志消息表明该方法是直接调用还是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();
    }
}

我希望可以通过比较来确定 的类是否this覆盖了 的实现。doWorkthis.doWorkDoerOfWork.prototype.doWork

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

如何检查方法是否已被覆盖或使用任何其他方法来确定当前执行的 ActionScript 方法是使用super调用还是直接调用?

4

2 回答 2

3

您可以将当前执行的函数作为arguments.callee. 从方法来看,这将MethodClosureDoerOfWork().doWork()with 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 中禁用严格模式。)

于 2013-03-05T01:22:16.483 回答
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 中 each的declaredBy属性<method>使用与 相同的格式flash.utils.getQualifiedClassName,我们可以比较这些来确定我们的实现是否被覆盖。

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

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

        calledWithSuper = currentImplementationFrom != thisImplementationFrom;

        trace("doWork called" + (calledWithSuper ? " (with super)." : "."));
    }
}
于 2013-03-05T01:22:32.393 回答