使用getdefinitionbyname后访问属性

时间:2017-03-24 17:32:46

标签: actionscript-3

我正在尝试从类这样的类访问属性:

public class Oak extends Tree //base class for tree classes
{
    public static const CLASS_NAME:String = getQualifiedClassName(Oak);

    public var branches:Array;

    public function Oak() 
    {
        branches = 
        [
        "Leaf1",
        "Leaf2",
        ];
    }

尝试访问变量的类如下所示:

public class TreeTest extends BaseScreen //just extends Sprite, TreeTest is shown on the stage
{
    public var oak:Tree;

    private var inc:int;

    public function TreeTest(pModel:Model) 
    {
        model = pModel;

        model.createTree(Oak.CLASS_NAME);
        oak = model.getTree(Oak.CLASS_NAME);
        inc = 0;

        this.addMouseClickListener(0, treeHandler); //from BaseScreen
    }

    private function treeHandler(e:MouseEvent):void 
    {
        inc++;
        this.displayText.text = oak.branches[inc];
    }

,模型如下所示:

public class Model 
{
    public var treeArray:Array;

    public function Model() 
    {
        treeArray = new Array();
    }

    public function createTree(pClassName:String):void 
    {
        var name:String = pClassName;
        var ClassReference:Class = getDefinitionByName(name) as Class;
        var classInstance:Tree = new ClassReference;
        treeArray.push([name, classInstance]);
    }

    public function getTree(pClassName:String):Tree
    {
        var treeName:String = pCharacterClassName;
        var match:Boolean = false;
        var matchArrayRef:int = 0;

        for (var i:int = 0; i < treeArray.length; i++) 
        {
            if (match == true) 
            {
                break
            }

            if (treeArray[i][0] == treeName) 
            {
                match = true;
                matchArrayRef = i;
            }
            else 
            {
                match = false;
            }
        }

        if (match == false) 
        {
            return null; 
        }
        else 
        {
            return treeArray[matchArrayRef][1];
        }
    }

当我运行它时,我收到错误“通过带有静态类型树的引用访问可能未定义的属性分支”。

在搜索解决方案之后,我发现这基本上意味着branches数组不在Tree类中。为了证实这一点,如果我去了公共var分支:远离Oak类的数组并将它放在Tree类中,代码就可以了。

为什么我不能访问Oak类中定义的变量,并且必须将所有内容放在Tree基类中?即使我将var classInstance:Tree更改为var classInstance:Oak,甚至var classInstance:Object,如果数组在Oak类中,我仍然会得到相同的错误,而不是Tree类。

就像,如果我创建一个新类Pine,它也会扩展Tree,我是否也必须将Pine的所有变量都放在Tree类中?

1 个答案:

答案 0 :(得分:1)

您将oak变量引用为类Tree,因此您从中引用的任何属性都应该是类Tree,而不是任何子类,因为超类没有它们因此编译器不知道如何从branches属性寻址内存。更糟糕的是,这种寻址在技术上可能从子类到子类不同,这就是为什么不能通过类型超类的引用直接寻址子类的属性。

有一种解决方法。您可以使用hasOwnProperty类中定义的Object方法检查某个树是否具有branches,然后通过基于字符串的寻址(如tree["branches"])进行寻址。

if (tree.hasOwnProperty("branches")) {
    var br=tree["branches"];
    trace(br); //or whatever
}

事实上,你甚至可以这样:

if (tree is Oak) {
    var oak:Oak=tree as Oak;
    // now all oaks have branches, go get em
    trace(oak.branches);
}

但是,这打破了面向对象编程的核心原则之一 - 您尝试显式依赖具有某些名称变量的子类,并期望它们在子类中包含相同含义的值。或者,使用第二种方法,您正在尝试使代码知道将存在的Tree的每个子类。实际上,您尝试使子类表现为超类,而不给超类提供足够的属性以便以通用方式提供该行为。这不是OOP的工作原理。因此,您应首先通过为泛型 Tree指定属性和方法来设计超类。所有树都有分支,因此branches应属于Tree类。例如,所有树木都可以grow(),无论是提供给生长的任何参数,还是湿度,温度,土壤厚度等,但它们对于Tree的所有子类都是相同的,无论是橡树还是橡树。因此,grow()方法也应该属于Tree类。但是,它们的增长方式不同,并且以不同的方式响应参数,但这是override帮助在子类中提供不同行为的地方。