我正在阅读有关创建AS3类的教程。我对构造函数感到困惑 - 它们是在创建类的新实例时执行的代码,对吧?但是,这一部分:
public function Greeter(initialName:String = "") {
name = initialName;
}
public var name:String;
public var name:String part不是构造函数的一部分,但它不应该在name变量设置的前面吗?
另外,第二个问题,什么是public var name:String;部分执行?当某些代码调用它时,将执行函数。并且在创建类的新实例时执行构造函数。但是那些代码中没有任何代码呢?
谢谢!
答案 0 :(得分:2)
AS编译器将自动重新组织您的代码。实际上,它看起来更像是这样:
public var name:String;
public function Greeter(initialName:String = "") {
name = initialName;
}
您可以通过执行以下操作来测试:
public var name:String = "Hello!";
public function Greeter(initialName:String = "") {
trace(name); // outputs Hello!
}
这也可行:
public function Greeter(initialName:String = "") {
trace(name); // outputs Hello!
}
public var name:String = "Hello!";
所有驻留在类中但在方法之外的代码(包括构造函数,这只是一种特殊方法)将在构造函数代码之前执行,这可能会有点误导。
一般情况下,除了最多设置上述变量之外,不要在方法之外做任何事情。通常,所有设置都应该在构造函数中完成。
修改强>
我正在更新我的答案,因此OP获得了正确的信息,即使已接受另一个答案。
编译器会重新编译代码。参见下图 - 我正在使用SoThink SWF反编译器,它显示SWF发布后类文件的状态。注意这条线是如何形成的,所以它实际上是重新组织的,所以它存在于类的顶层。
调用该类的Flash文档
班级代码(注意底部的变量)
反编译的SWF类代码(注意顶部的变量)出于兴趣,还要注意Flash内部如何更改变量名称,例如param1等
如果你有sothink反编译器,你可以自己试试。
答案 1 :(得分:2)
在您的示例中,您正在显示一个名为成员变量的内容。成员变量是在var
和相应的class <ClassName>{
之间声明为}
的东西(该区域是“类的主体”)。虽然从技术上讲它可以出现在课堂的任何地方,但最常见的却是最顶层的。
构造实例类时,将分配这些变量的heap
空间。因此,在您的情况下,除了在调用new Greeter()
时在内存中创建的原始对象之外,还包括name
的特殊位置。在您的特定情况下,构造函数还为该属性赋值,但该属性也可能为null
。
每个未标记为var
的{{1}}都是成员变量。这意味着它是该变量实例的特定属性。这意味着您可以拥有50个Greeters,它们都具有不同的名称 - 它们都可以具有不同的成员变量值。另一方面,如果您有static
,则表示您无法简单地访问Greeter的名称,但您必须访问值static var name
。在类(以及类的子级)中,您将能够将名称作为一种局部变量访问,世界其他地方不能简单地执行:
Greeter.name
相反,他们需要将其作为该类的属性来解决:
var g:Greeter = new Greeter();
g.name = "foo"; //this would cause an error
答案 2 :(得分:1)
我相信Action Script在声明类变量的位置并不重要。虽然包括AS在内的大多数C风格的语言都不需要在使用之前声明变量,但Pascal风格的语言确实迫使你这样做。
Greeter classe的所有方法都可以看到var name
,但如果它是在构造函数(局部变量)中声明的,那么它只能在构造函数的范围内可用。如果声明一个局部变量,那么该类的其他成员无法访问它。在这种情况下,var name
被声明为一个类变量,该类变量旨在对类的所有成员可见(成员我指的是方法和构造函数和属性)。此外,因为它是一个公共类变量,所以它可以访问引用Greeter类实例的其他代码。
大多数编译器初始化原始变量(例如,布尔值为false,Ints为0)。然而,非基本类型保留为null。您应该将构造函数视为准备要使用的对象的新实例的一些逻辑。除了初始化之外,它通常不应该执行其他代码。