【问题标题】:Conflicting Scope: Global Functions and Class Methods of the Same Name冲突范围:同名的全局函数和类方法
【发布时间】:2011-07-06 15:46:17
【问题描述】:

我的问题直接涉及 ActionScript 3,尽管它可能出现在其他语言中。

考虑在 AS3 中找到的全局 trace 函数。调用该方法不需要导入,并且可从所有类全局使用。

class A {

    public function A() {
        trace("Hello, A!"); // Hello, A!
    }

}

现在,如果我创建自己的同名类方法会怎样?在 AS3 中,如果我有一个类方法 trace,然后在我的类中的其他地方调用 trace,则通过全局函数调用类方法。从本质上讲,我已经阻止了调用全局跟踪方法的能力。

class B {

    public function B() {
        trace("Hello, B!"); // no output
    }

    public function trace(s:String):void {
        // do something else.
    }

}

现在,我知道显而易见的答案是“不要创建名为 trace 的类方法。”但是如果我不知道全局 trace 函数的存在怎么办?或者,如果我想“覆盖”或“阻止”全局函数怎么办?编程就这么糟糕吗?或者这只是 AS3 是一种糟糕的面向对象语言的另一个例子?

【问题讨论】:

  • 隐藏最常见的名字在任何语言中都是不好的。

标签: actionscript-3 function methods scope global


【解决方案1】:

导入 flash.uitls.*;

那么你可以使用

(getDefinitionByName('trace') as Function)('Global trace.');

【讨论】:

    【解决方案2】:

    如果您的函数 trace 不是 public 您可以使用 public namespace 来调用原始函数:

    class B {
        public function B() {
            // call the trace function that is defined in the public namespace
            public::trace("Hello, B!"); // output "Hello, B!"
        }
    
        // here the function is protected so not into the public namespace
        protected function trace(s:String):void {
            // do something else.
        }
    }
    

    【讨论】:

      【解决方案3】:

      “但是如果我不知道全局跟踪函数的存在呢?”

      我认为这更多地表明您尚未对语言研究进行尽职调查,而不是语言本身的缺陷。 AS3 中的顶级名称和关键字很少,我认为如果您对学习一门语言感兴趣,您至少应该熟悉该顶级。

      【讨论】:

      • 我认为'trace'实际上是一个不好的例子。就在几天前,我遇到了一个真实世界的情况,它使用了位于全局命名空间中的“向量”函数。我有一个遗留项目(在引入 Vector 之前编写),它使用了一个与数学相关的类,称为 - 猜猜看 - Vector。我需要为更新的 Flash 版本重新编译,然后 bam!该项目不想编译,并且无论在哪里使用 Vector 类,我都会得到错误。我同意 OP 的观点,即这是 Adob​​e 的糟糕设计。为什么他们不把 Vector 函数放在自己的包里?
      • @RIAstar Vector 是一个奇怪的例子,因为它可以被认为是一个像 int 或 uint 这样的原语。在大小为 N 的连续内存块的意义上,它们接近于真正的数组,其中 N 等于所需数据类型的大小。这与 AS3 “Array” 形成对比,后者更像是一个无类型的 ArrayList。无论如何,原语不属于包,因此 Vector 不存在于包中。这当然很不幸,但我理解为什么会这样。
      • Array 和 Vector 都不是基元,因为 1 == 1 或 "a" == "a" 的计算结果为“真”,但 [1] == [1] 没有。它们是内置(或顶级)集合。
      【解决方案4】:

      另一种方法是更改​​名称绑定到全局标识符的位置,例如使用以下包装类:

      class B {
          public function B() {
              Globals.global_trace("Hello, B!"); // delegates to global trace()
          }
          public function trace(s:String):void {
              // do something else.
          }
      }
      
      class Globals {
          public function global_trace(...args) {
              // class B's identifiers are now irrelevant for the name lookup
              trace.apply(null, args);
          }
      }
      

      更本地化的方法是在隐藏全局符号之前重新绑定它:

      private static var _trace:* = trace; // rebind global trace
      
      public function trace(...args) {
          _trace.apply(null, args);
      }
      

      【讨论】:

        猜你喜欢
        • 2013-04-13
        • 1970-01-01
        • 2013-06-30
        • 1970-01-01
        • 2014-12-24
        • 1970-01-01
        • 1970-01-01
        • 2012-03-08
        • 2017-01-20
        相关资源
        最近更新 更多