【问题标题】:How to Override Constants in ActionScript 3如何在 ActionScript 3 中覆盖常量
【发布时间】:2012-10-05 06:28:11
【问题描述】:

我有以下两个课程:

public class Parent{
    static internal const _name:String = "Parent";

    public function get name():String{
        return _name;
    }
}

public class Child{
    static internal const _name:String = "Child";
}

如果我创建一个 Child 类的实例并调用它的 name() getter,因为它将调用它从 Parent 继承的 name() 方法,所以它返回“Parent”。当然,我可以覆盖 name() 方法:

public class Child{
    static internal const _name:String = "Child";

    override public function get name():String{
        return _name;
    }
}

返回“孩子”。但是,必须从父级复制完全相同的方法代码似乎很愚蠢。有没有更简单的方法来做到这一点?

【问题讨论】:

  • 您是否需要类似于 DisplaysObject 名称属性的实例名称?或者你不想有一个可用的类名?
  • 这只是对实际问题的简化。在现实生活中,我的常量不称为名称,它是一个更复杂的数据结构,我想将其设为静态,因为它由类的所有实例共享
  • 也许是我,但我看不到问题所在。如果你正在扩展一个类,你也继承了类的属性。如果要覆盖类属性之一的定义,则必须覆盖它。您可能需要重新考虑您的设计。
  • 这不是一个大问题。我只是想知道是否有一种更简洁的方法,它不涉及将方法定义从父类复制和粘贴到子类,因为它是相同的。我发现使用原型对象(如我发布的自我回答中所述)可以解决问题并且效果很好。

标签: actionscript-3 flash apache-flex


【解决方案1】:

我会采取不同的方法,将“name”属性作为父构造函数的要求:

public class Parent
{
    static internal var _name : String;

    public function Parent(name : String = "Parent") {
        _name = name;
    }

    public function get name() : String {
        return _name;
    }
}

儿童班:

public class Child extends Parent
{   
    public function Child() {
        super("Child");
    }
}

【讨论】:

  • 但是 _name 是静态的,所以它是由所有实例共享的。但这是一个好点,我会将 _name 从 var 更改为 const。
【解决方案2】:

首先,您不能覆盖静态方法或属性 - 它们不是继承的,因此不能覆盖它们。

其次,如果您将常量声明为复杂类型,则它并不是真正的常量。 IE。如果是对象,则可以更改其键/值,如果是数组,则可以添加/删除成员等等。

但是让这个功能更通用的愿望是可以理解的。所以,我会怎么做:

在父母和孩子之外都有一些财产,比如说在班级X,或包Y。让它成为包Y。所以,你会在包Y 中创建一个字典,让它成为Y.names 并以你的名义getter 你会这样做:

import Y.names;
. . .
public function get name() {
    return names[(this as Object).constructor];
}

你的名字变量是:

package Y {

    public var names:Dictionary = generateNames();

    internal function generateNames():Dictionary {
        var result:Dictionary = new Dictionary();
        result[ChildClass] = "child";
        result[ParentClass] = "parent";
        . . .
        return result;
    }
}

这样在超类中只实现name getter就足够了,所有继承类都可以使用超类的代码,不需要做任何改变。但是,这意味着与该类有关的一些(可能很重要)信息将存储在其他地方(可能很难找到,这不是人们在 AS3 中编程的常用方式)。

【讨论】:

  • 这行得通。不过,我对每次创建新子类时都必须修改 generateNames() 感到不高兴。我的 Parent 基类是我想通过子类化的方式在许多项目中重用的东西。
  • 正如 wvxvw 所说,常量只设置一次,所以只需去掉常量关键字 - 只要 static 就可以按照你的意愿去做 - 来自类的所有实例的相同访问。
  • 是的,在这一点上,我真的不介意它是 var 还是 const。我只是在 manatube 发布他的答案后把它放在那里,以使我的问题更清楚。但是,我想保持我的类密封,而不必每次必须从基类继承新类时都返回并更改方法。
  • +1 用于指定不继承静态方法/属性。我想说静态方法/属性存在于类而不是类的实例上。
【解决方案3】:

您的 get name 实现应该如下所示,然后 getter 是一个,并且每个新类需要拥有自己的 public static var _name 定义:

//in the base class
    public function get name():String 
    {
        var _sName:String;
        if ((this as Object).constructor._name)
        {
            _sName = (this as Object).constructor._name; 
        }
        else
        {
            try
            {
                var o:Object = getSuperClass(this);
                while (o)
                {
                    if (o._name)
                    {
                        _sName = o._name;
                        break;
                    }
                    o =  getSuperClass(o);
                }
            }
            catch (e:*)
            {}
        }
        return _sName;
    }
//as found here: http://www.actionscriptdeveloper.co.uk/getting-the-class-of-an-object-in-as3/
public static function getSuperClass(o: Object): Object
{
    var n: String = getQualifiedSuperclassName(o);
    if (n == null)
        return(null);

    return getDefinitionByName(n);
}

静态成员只能通过类引用来访问,我们可以从构造函数对象中获取,“this”将指向继承链中的当前类,因此您可以在父类中调用this,它将指向一个子类一个子类。

[编辑] 我已经对其进行了修改,因此如果在“this”实例上找不到公共静态属性_name,它会测试是否存在,然后在循环中检查父类,直到找到一个 - 就像继承一样:)

我正在使用此功能创建克隆方法:constructor as helper in clone method implementation

最好的问候

【讨论】:

  • 我看起来很有趣,我有预感这会解决它,但我只是尝试了一下,结果我得到了 null。
  • 我做了一些测试,如果我将 _name 更改为公开而不是私有,它确实有效。但是,如果我没有在 Child 类中定义 _name(它不是从父类继承),它就不起作用。
  • 可能会提供有关您的问题的更多详细信息,以便我们可以看到您的用例,从而更容易匹配解决方案:)
  • 我正在尝试为要序列化为 JSON 并返回的对象编写一个基类。我在 IList 变量及其从 JSON 数组返回的序列化方面遇到了一些麻烦。为了解决这个问题,我正在考虑有一个可以被后代类覆盖的类属性,它可以保存有关如何映射这些变量的信息。
  • 我已经加分了你的答案,因为它是导致我发现原型对象的原因。我认为您在代码中所做的或多或少是原型所做的。
【解决方案4】:

为什么不将这样的常量存储在相应的函数中,而不是声明一个不可访问的常量?

class Parent {
    ...
    public function get name():String { return 'Parent'; }
}
class Child extends Parent {
    ...
    override public function get name():String { return 'Child'; }
}

顺便说一下,如果您的 Parent 类是 DisplayObject 的后代,您应该小心使用 name 属性,因为有时操作代码需要它,例如getChildByName().

【讨论】:

  • 不错且简单的解决方案。您知道返回的是静态对象还是每次调用函数时都会分配它? (现实生活中不会是字符串而是Object,不会叫“name”)
  • 抱歉,无法帮助分配,因为这对我来说是一块未开发的土地。我希望这是一个动态的结果。但是,AS3 中字符串实际发生的任何事情都很好地隐藏在 Flash 引擎后面,也许不应该过度优化这个部门。
  • 我刚刚运行了一个小测试,每次调用该函数时都会分配一个新对象。 :(
  • 如果是这样,那么您的方式似乎是最理想的,即使不是那么简单。生活并不总是既简单又高效。
  • 我实际上喜欢使用原型的方式,我发现它试图让 Lukasz 的想法在我的特定情况下发挥作用。但是,由于我以前从未使用过原型,所以我想听听任何问题。
【解决方案5】:

我发现了一些似乎可行的方法。非常感谢任何反馈:

public class Parent{
    prototype._name = "Parent";

    public function get name():String{
        return this["_name"];
    }
}

public class Child{
    prototype._name = "Child";
}

【讨论】:

  • 我同意。不过,在我的用例中,它似乎有效。我只是希望我不会错过一些大缺点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-30
  • 1970-01-01
  • 2011-03-11
  • 1970-01-01
  • 1970-01-01
  • 2011-03-18
  • 1970-01-01
相关资源
最近更新 更多