我正在尝试从类这样的类访问属性:
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类中?
答案 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
帮助在子类中提供不同行为的地方。