类

类是对象的抽象表示形式。类用来存储有关对象可保存的数据类型及对象可表现的行为的信息。如果编写的小脚本中只包含几个彼此交互的对象,使用这种抽象类的作用并不一定明显。然而,随着程序的作用域不断扩大,必须管理的对象数量也在增加。在这种情况下,通过类可以更好地控制创建对象的方式以及对象彼此交互的方式。

早在 ActionScript 1.0 中,ActionScript 程序员就能使用 Function 对象创建类似类的构造函数。在 ActionScript 2.0 中,通过使用 class 和 extends 等关键字,正式添加了对类的支持。ActionScript 3.0 不仅继续支持 ActionScript 2.0 中引入的关键字,而且还添加了新功能。例如,ActionScript 3.0 包含对 protected 和 internal 属性的增强的访问控制。它还通过使用 final 和 override 关键字,提供了更好的继承控制。

对于使用过 Java、 C++ 或 C# 等编程语言创建类的开发人员,ActionScript 提供了熟悉的体验。ActionScript 共享许多相同的关键字和属性名称,例如 class 、 extends 和 public 。

注: 在 Adobe ActionScript 文档中,术语“属性”表示对象或类的任何成员,包括变量、常量和方法。此外,虽然术语“类”和“静态”经常互换使用,但在本章中这两个术语是不同的。例如,“类属性”指的是类的所有成员,而不仅是静态成员。

类定义

ActionScript 3.0 类定义使用的语法与 ActionScript 2.0 类定义使用的语法相似。正确的类定义语法要求 class 关键字后跟类名。类体要放在大括号 ( {} ) 内,且放在类名后面。例如,下面的代码创建名为 Shape 的类,其中包含名为 visible 的变量:

public class Shape 
{ 
    var visible:Boolean = true; 
}

对于包中的类定义,有一项重要的语法更改。在 ActionScript 2.0 中,如果类在包中,则在类声明中必须包含包名称。在 ActionScript 3.0 中,引入了 package 语句,包名称必须包含在包声明中,而不是包含在类声明中。例如,以下类声明说明如何在 ActionScript 2.0 和 ActionScript 3.0 中定义 BitmapData 类(该类是 flash.display 包的一部分):

// ActionScript 2.0 
class flash.display.BitmapData {} 
 
// ActionScript 3.0 
package flash.display 
{ 
    public class BitmapData {} 
}

类属性

在 ActionScript 3.0 中,可使用以下四个属性之一来修改类定义:

属性

定义

dynamic

允许在运行时向实例添加属性。

final

不得由其他类扩展。

internal (默认)

对当前包内的引用可见。

public

对所有位置的引用可见。

使用 internal 以外的每个属性时,显式包含该属性才能实现相关的行为。例如,如果定义类时未包含 dynamic 属性,则不能在运行时向类实例中添加属性。通过在类定义的开始处放置属性,可显式地分配属性,如下面的代码所示:

dynamic class Shape {}

请注意,列表中未包含名为 abstract 的属性。ActionScript 3.0 不支持抽象类。另请注意,该列表也未包含名为 private 和 protected 的属性。这些属性只在类定义中有意义,但不可以应用于类本身。如果不希望某个类在包以外公开可见,请将该类放在包中,并用 internal 属性标记该类。或者,可以省略 internal 和 public 这两个属性,编译器会自动为您添加 internal 属性。还可以将类定义为仅在定义此类的源文件内可见。将类置于源文件的底部,包定义的右大括号下方。

类体

类体用大括号括起来。类体定义类的变量、常量和方法。以下示例显示 ActionScript 3.0 中对 Accessibility 类的声明:

public final class Accessibility 
{ 
    public static function get active():Boolean; 
    public static function updateProperties():void; 
}

还可以在类体中定义命名空间。下面的示例说明如何在类体中定义命名空间,以及如何在该类中将命名空间用作方法的属性:

public class SampleClass 
{ 
    public namespace sampleNamespace; 
    sampleNamespace function doSomething():void; 
}

ActionScript 3.0 不但允许在类体中包括定义,而且还允许包括语句。位于类体内但在方法定义之外的语句,实际执行次数严格为一次。这在第一次遇到类定义并创建关联的类对象时执行。下面的示例包括一个对 hello() 外部函数的调用和一个 trace 语句,该语句在定义类时输出确认消息:

function hello():String 
{ 
    trace("hola"); 
} 
class SampleClass 
{ 
    hello(); 
    trace("class created"); 
} 
// output when class is created 
hola 
class created

在 ActionScript 3.0 中,允许在同一类体中定义同名的静态属性和实例属性。例如,下面的代码声明一个名为 message 的静态变量和一个同名的实例变量:

class StaticTest 
{ 
    static var message:String = "static variable"; 
    var message:String = "instance variable"; 
} 
// In your script 
var myST:StaticTest = new StaticTest(); 
trace(StaticTest.message); // output: static variable 
trace(myST.message); // output: instance variable

类属性的属性

讨论 ActionScript 对象模型时,术语 属性 指可以作为类成员的任何成员,包括变量、常量和方法。不过,在《用于 Adobe Flash Platform 的 Adobe ActionScript 3.0 参考》中,该术语的使用范围比较严格。在该上下文中,属性这一术语仅包含作为变量或通过 getter 或 setter 方法定义的类成员。ActionScript 3.0 中提供了一组可以与类的任何属性一起使用的属性。下表列出了这组属性。

属性

定义

internal (默认)

对同一包中的引用可见。

private

对同一类中的引用可见。

protected

对同一类及派生类中的引用可见。

public

对所有位置的引用可见。

static

指定某一属性属于该类,而不属于该类的实例。

UserDefinedNamespace(用户定义的命名空间)

用户定义的自定义命名空间名。

访问控制命名空间属性

ActionScript 3.0 提供了四个特殊的属性来控制对在类中定义的属性的访问: public 、 private 、 protected 和 internal 。

public 属性使某一属性在脚本的任何位置可见。例如,要使某个方法可用于包外部的代码,必须使用 public 属性声明该方法。这适用于任何属性,不管属性是使用 var 、 const 还是 function 关键字声明的。

private 属性使某一属性只对属性的定义类中的调用方可见。这一行为与 ActionScript 2.0 中的 private 属性有所不同,后者允许子类访问超类中的私有属性。另一处明显的行为变化是必须执行运行时访问。在 ActionScript 2.0 中, private 关键字只在编译时禁止访问,运行时很容易避开它。在 ActionScript 3.0 中,这种情况不复存在。标记为 private 的属性在编译时和运行时都不可用。

例如,下面的代码创建一个带一个私有变量的名为 PrivateExample 的简单类,然后尝试从该类的外部访问该私有变量。

class PrivateExample 
{ 
    private var privVar:String = "private variable"; 
} 
 
var myExample:PrivateExample = new PrivateExample(); 
trace(myExample.privVar);// compile-time error in strict mode 
trace(myExample["privVar"]); // ActionScript 2.0 allows access, but in ActionScript 3.0, this is a run-time error. 

在 ActionScript 3.0 中使用严格模式时,尝试使用点运算符 ( myExample.privVar ) 访问私有属性会导致编译时错误。否则,会在运行时报告错误,就像使用属性访问运算符 ( myExample["privVar"] ) 时一样。

下表汇总了试图访问属于密封(非动态)类的 private 属性的结果:

严格模式

标准模式

点运算符 ( . )

编译时错误

运行时错误

中括号运算符 ( [] )

运行时错误

运行时错误

在使用 dynamic 属性声明的类中尝试访问私有变量不会导致运行时错误。但是,变量不可见,因此返回值 undefined 。但是,如果在严格模式下使用点运算符,则会发生编译时错误。下面的示例与上一个示例相同,只是 PrivateExample 类被声明为动态类:

dynamic class PrivateExample 
{ 
    private var privVar:String = "private variable"; 
} 
 
var myExample:PrivateExample = new PrivateExample(); 
trace(myExample.privVar);// compile-time error in strict mode 
trace(myExample["privVar"]); // output: undefined

当类外部的代码尝试访问 private 属性时,动态类通常会返回值 undefined ,而不是生成错误。下表说明了只有在严格模式下使用点运算符访问 private 属性时才会生成错误:

严格模式

标准模式

点运算符 ( . )

编译时错误

undefined

中括号运算符 ( [] )

undefined

undefined

protected 属性是 ActionScript 3.0 中的新增属性,可使某一属性对于其所属类或子类中的调用方可见。换句话说,protected 属性在其所属类中可用,或者对继承层次中该类下面的类可用。无论子类在同一包中还是在不同包中,这一点都适用。

对熟悉 ActionScript 2.0 的人来说,本功能类似于 ActionScript 2.0 中的 private 属性。ActionScript 3.0 中的 protected 属性也类似于 Java 中的 protected 属性。不同之处在于 Java 版本还允许访问同一包中的调用方。如果存在子类需要的变量或方法,但要对继承链外部的代码隐藏该变量或方法,此时 protected 属性会很有用。

internal 属性是 ActionScript 3.0 的新增属性,可使某一属性对所在包中的调用方可见。该属性是包中代码的默认属性,它适用于任何没有以下任意属性的属性:

  • public

  • private

  • protected

  • 用户定义的命名空间

internal 属性与 Java 中的默认访问控制相似,不过,在 Java 中该访问级别没有明确的名称,只能通过省略所有其他访问修饰符来实现。ActionScript 3.0 中提供的 internal 属性旨在为您提供一个明确表达自己意图的选项,以使属性仅对所在包中的调用方可见。

static 属性

static 属性可以与用 var 、 const 或 function 关键字声明的那些属性一起使用,使用该属性可将属性附加到类而不是类的实例。类外部的代码必须使用类名(而不是使用实例名)调用静态属性。

静态属性不由子类继承,但是这些属性是子类作用域链中的一部分。这意味着在子类体中,不必引用在其中定义静态变量或方法的类,就可以使用静态变量或方法。

用户定义的命名空间属性

作为预定义访问控制属性的替代方法,您可以创建自定义命名空间以用作属性。每个定义只能使用一个命名空间属性,而且不能将命名空间属性与任何访问控制属性( public 、 private 、 protected 和 internal )组合使用。

变量

可以使用 var 或 const 关键字声明变量。在脚本的整个执行过程中,使用 var 关键字声明的变量可多次更改其变量值。使用 const 关键字声明的变量称为 常量 ,只能赋值一次。尝试给已初始化的常量分配新值,将生成错误。

静态变量

静态变量是使用 static 关键字和 var 或 const 语句共同声明的。静态变量附加到类而不是类的实例,对于存储和共享应用于对象的整个类的信息非常有用。例如,当要保存类实例化的总次数或者要存储允许的最大类实例数,使用静态变量比较合适。

下面的示例创建一个 totalCount 变量(用于跟踪类实例化数)和一个 MAX_NUM 常量(用于存储最大实例化数)。 totalCount 和 MAX_NUM 这两个变量是静态变量,因为它们包含的值应用于整个类,而不是某个特定实例。

class StaticVars 
{ 
    public static var totalCount:int = 0; 
    public static const MAX_NUM:uint = 16; 
}

StaticVars 类及其任何子类外部的代码只能通过该类本身来引用 totalCount 和 MAX_NUM 属性。例如,以下代码有效:

trace(StaticVars.totalCount); // output: 0 
trace(StaticVars.MAX_NUM); // output: 16

不能通过类实例访问静态变量,因此以下代码会返回错误:

var myStaticVars:StaticVars = new StaticVars(); 
trace(myStaticVars.totalCount); // error 
trace(myStaticVars.MAX_NUM); // error

必须在声明常量的同时初始化使用 static 和 const 关键字声明的变量,就像 StaticVars 类初始化 MAX_NUM 那样。您不能为构造函数或实例方法中的 MAX_NUM 赋值。以下代码会生成错误,因为它不是初始化静态常量的有效方法:

// !! Error to initialize static constant this way 
class StaticVars2 
{ 
    public static const UNIQUESORT:uint; 
    function initializeStatic():void 
    { 
        UNIQUESORT = 16; 
    } 
}

实例变量

实例变量包括使用 var 和 const 关键字但未使用 static 关键字声明的属性。实例变量附加到类实例而不是整个类,对于存储特定于实例的值很有用。例如,Array 类有一个名为 length 的实例属性,用来存储 Array 类的特定实例保存的数组元素的个数。

不能覆盖子类中声明为 var 或 const 的实例变量。但是,通过覆盖 getter 和 setter 方法,可以实现类似于覆盖变量的功能。

方法

方法是类定义中的函数。创建类的一个实例后,该实例就会捆绑一个方法。与在类外部声明的函数不同,不能将方法与附加方法的实例分开使用。

方法是使用 function 关键字定义的。至于任一类属性,可以将任一类属性应用到方法,这些属性包括 private、protected、public、internal、static,或者自定义命名空间。您可以使用函数语句,例如:

public function sampleFunction():String {}

也可以使用分配了函数表达式的变量,如下所示:

public var sampleFunction:Function = function () {}

多数情况下都使用函数语句,而不是函数表达式,原因如下:

  • 函数语句更为简洁易读。

  • 函数语句允许使用 override 和 final 关键字。

  • 函数语句在标识符(函数名)与方法体代码之间创建了更强的绑定。由于可以使用赋值语句更改变量值,因此可随时断开变量与其函数表达式之间的连接。虽然可通过使用 const (而不是 var )声明变量来解决这个问题,但这种方法并不是最好的做法。这会使代码难以阅读,还会阻止使用 override 和 final 关键字。

必须使用函数表达式的一种情况是:选择将函数附加到原型对象时。

构造函数方法

构造函数方法有时称为 构造函数 ,是与在其中定义函数的类共享同一名称的函数。只要使用 new 关键字创建了类实例,就会执行构造函数方法中包括的所有代码。例如,以下代码定义名为 Example 的简单类,该类包含名为 status 的属性。 status 变量的初始值是在构造函数中设置的。

class Example 
{ 
    public var status:String; 
    public function Example() 
    { 
        status = "initialized"; 
    } 
} 
 
var myExample:Example = new Example(); 
trace(myExample.status); // output: initialized

构造函数方法只能是公共方法,但可以选择性地使用 public 属性。不能对构造函数使用任何其他访问控制说明符(包括使用 private 、 protected 或 internal )。也不能对函数构造方法使用用户定义的命名空间。

构造函数可以使用 super() 语句显式地调用其直接超类的构造函数。如果未显式调用超类构造函数,编译器会在构造函数体中的第一个语句前自动插入一个调用。还可以使用 super 前缀作为对超类的引用来调用超类的方法。如果决定在同一构造函数中使用 super() 和 super ,务必先调用 super() 。否则, super 引用的行为会与预期不符。另外, super() 构造函数也应在 throw 或 return 语句之前调用。

下面的示例说明如果在调用 super() 构造函数之前尝试使用 super 引用,将会发生什么情况。新类 ExampleEx 扩展了 Example 类。ExampleEx 构造函数尝试访问在其超类中定义的状态变量,但访问是在调用 super() 之前进行的。ExampleEx 构造函数中的 trace() 语句生成了 null 值,原因是 status 变量在 super() 构造函数执行之前不可用。

class ExampleEx extends Example 
{ 
    public function ExampleEx() 
    { 
        trace(super.status); 
        super(); 
    } 
} 
 
var mySample:ExampleEx = new ExampleEx(); // output: null

虽然在构造函数中使用 return 语句是合法的,但是不允许返回值。换句话说, return 语句不得有相关的表达式或值。因此,不允许构造函数方法返回值,这意味着不可以指定任何返回值。

如果没有在类中定义构造函数方法,编译器会自动为您创建一个空构造函数。如果某个类扩展了另一个类,编译器会在所生成的构造函数中包括 super() 调用。

静态方法

静态方法也叫做 类方法 ,它们是使用 static 关键字声明的方法。静态方法附加到类而不是类的实例,因此在封装对单个实例的状态以外的内容有影响的功能时,静态方法很有用。由于静态方法附加到整个类,所以只能通过类访问静态方法,而不能通过类实例访问。

静态方法为封装所提供的功能不仅仅在影响类实例状态的方面。换句话说,如果方法提供的功能对类实例的值没有直接的影响,该方法应是静态方法。例如,Date 类具有名为 parse() 的静态方法,它接收字符串并将其转换为数字。该方法就是静态方法,因为它并不影响类的单个实例。而 parse() 方法使用表示日期值的字符串,分析该字符串,然后使用与 Date 对象的内部表示形式兼容的格式返回一个数字。此方法不是实例方法,因为将该方法应用到 Date 类的实例并没有任何意义。

请将静态 parse() 方法与 Date 类的一个实例方法(如 getMonth() )相比较。 getMonth() 方法是一个实例方法,因为它通过检索 Date 实例的特定组件(即 month),对实例值直接执行操作。

由于静态方法不绑定到单个实例,因此不能在静态方法体中使用关键字 this 或 super 。 this 和 super 这两个引用只在实例方法上下文中有意义。

与其他基于类的编程语言不同,ActionScript 3.0 中的静态方法不是继承的。

实例方法

实例方法指的是不使用 static 关键字声明的方法。实例方法附加到类实例而不是整个类,在实现对类的各个实例有影响的功能时,实例方法很有用。例如,Array 类包含名为 sort() 的实例方法,该实例方法直接对 Array 实例执行操作。

在实例方法体中,静态变量和实例变量都在作用域中,这表示使用一个简单的标识符可以引用同一类中定义的变量。例如,以下类 CustomArray 扩展了 Array 类。CustomArray 类定义一个名为 arrayCountTotal 的静态变量(用于跟踪类实例总数)、一个名为 arrayNumber 实例变量(用于跟踪创建实例的顺序)和一个名为 getPosition() 的实例方法(用于返回这两个变量的值)。

public class CustomArray extends Array 
{ 
    public static var arrayCountTotal:int = 0; 
    public var arrayNumber:int; 
 
    public function CustomArray() 
    { 
        arrayNumber = ++arrayCountTotal; 
    } 
     
    public function getArrayPosition():String 
    { 
         return ("Array " + arrayNumber + " of " + arrayCountTotal); 
    } 
}

虽然类外部的代码必须使用 CustomArray.arrayCountTotal 通过类对象来访问 arrayCountTotal 静态变量,但是位于 getPosition() 方法体中的代码可以直接引用静态 arrayCountTotal 变量。即使对于超类中的静态变量,这一点也适用。虽然在 ActionScript 3.0 中不继承静态属性,但是超类的静态属性在作用域中。例如,Array 类有几个静态变量,其中一个是名为 DESCENDING 的常量。位于 Array 子类中的代码可以使用一个简单的标识符来访问静态常量 DESCENDING :

public class CustomArray extends Array 
{ 
    public function testStatic():void 
    { 
        trace(DESCENDING); // output: 2 
    } 
}

实例方法体中的 this 引用的值是对方法所附加实例的引用。下面的代码说明 this 引用指向包含方法的实例:

class ThisTest 
{ 
    function thisValue():ThisTest 
    { 
        return this; 
    } 
} 
 
var myTest:ThisTest = new ThisTest(); 
trace(myTest.thisValue() == myTest); // output: true

使用关键字 override 和 final 可以控制实例方法的继承。可以使用 override 属性重新定义继承的方法,以及使用 final 属性禁止子类覆盖方法。

get 和 set 存取器方法

get 和 set 存取器函数还分别称为 getter 和 setter ,可以使用这些函数为创建的类提供易于使用的编程接口,并遵循信息隐藏和封装的编程原则。使用 get 和 set 函数可保持类的私有类属性,但允许类用户访问这些属性,就像他们在访问类变量而不是调用类方法。

这种方法的好处是,可避免出现具有不实用名称的传统存取器函数,如 getPropertyName() 和 setPropertyName() 。getter 和 setter 的另一个好处是,使用它们可避免允许进行读写访问的每个属性有两个面向公共的函数。

下面的示例类名为 GetSet,其中包含名为 publicAccess() 的 get 和 set 存取器函数,用于提供对名为 privateProperty 的私有变量的访问:

class GetSet 
{ 
    private var privateProperty:String; 
     
    public function get publicAccess():String 
    { 
        return privateProperty; 
    } 
     
    public function set publicAccess(setValue:String):void 
    { 
        privateProperty = setValue; 
    } 
}

如果尝试直接访问属性 privateProperty ,将发生错误,如下所示:

var myGetSet:GetSet = new GetSet(); 
trace(myGetSet.privateProperty); // error occurs

GetSet 类的用户所使用的对象是显示为名为 publicAccess 的属性,但实际上这是对名为 privateProperty 的 private 属性执行的一对 get 和 set 取值函数。下面的示例将实例化 GetSet 类,然后使用名为 publicAccess 的公共存取器设置 privateProperty 的值:

var myGetSet:GetSet = new GetSet(); 
trace(myGetSet.publicAccess); // output: null 
myGetSet.publicAccess = "hello"; 
trace(myGetSet.publicAccess); // output: hello

使用 getter 和 setter 函数还可以覆盖从超类继承来的属性,这是使用常规类成员变量时不能做到的。在子类中不能覆盖使用 var 关键字声明的类成员变量。但是,使用 getter 和 setter 函数创建的属性没有此限制。可以对从超类继承的 getter 和 setter 函数使用 override 属性。

绑定方法

绑定方法有时也叫做 闭包方法 ,就是从它的实例提取的方法。作为参数传递给函数的方法或作为值从函数返回的方法都是绑定方法。在 ActionScript 3.0 中,新增的绑定方法类似于闭包函数,其中保留了词汇环境,即使从其实例中提取出来也是如此。绑定方法与闭包函数之间的主要不同差别是,绑定函数的 this 引用保留到实现方法的实例的链接或绑定。换句话说,绑定方法中的 this 引用总是指向实现方法的原始对象。对于闭包函数, this 引用是通用的,这意味着调用函数时,该引用指向与函数关联的任何对象。

如果使用 this 关键字,了解绑定方法就很重要。重新调用 this 关键字可提供对方法父对象的引用。大多数 ActionScript 编程人员都希望 this 关键字总是表示包含方法定义的对象或类。但是,如果不使用方法绑定,并不是总是做到这样。例如,在以前版本的 ActionScript 中, this 引用并不总是引用实现方法的实例。从 ActionScript 2.0 的实例中提取方法后,不但 this 引用不绑定到原始实例,而且实例类的成员变量和方法也不可用。在 ActionScript 3.0 中不存在这样的问题,这是因为将方法当作参数传递时会自动创建绑定方法。绑定方法用于确保 this 关键字总是引用在其中定义了方法的对象或类。

下面的代码定义了名为 ThisTest 的类,该类包含一个名为 foo() 的方法(该方法定义绑定方法)和一个名为 bar() 的方法(该方法返回绑定方法)。类外部的代码创建 ThisTest 类的实例,然后调用 bar() 方法,最后将返回值存储在名为 myFunc 的变量中。

class ThisTest 
{ 
    private var num:Number = 3; 
    function foo():void // bound method defined 
    { 
        trace("foo's this: " + this); 
        trace("num: " + num); 
    } 
    function bar():Function 
    { 
        return foo; // bound method returned 
    } 
} 
 
var myTest:ThisTest = new ThisTest(); 
var myFunc:Function = myTest.bar(); 
trace(this); // output: [object global] 
myFunc(); 
/* output:  
foo's this: [object ThisTest] 
output: num: 3 */

代码的最后两行表明:虽然前一行中的 this 引用指向全局对象,但绑定方法 foo() 中的 this 引用仍然指向 ThisTest 类的实例。另外,存储在 myFunc 变量中的绑定方法仍然可以访问 ThisTest 类的成员变量。如果以上代码在 ActionScript 2.0 中运行, this 引用会匹配,但 num 变量将为 undefined 。

绑定方法最值得注意的一种情况是使用事件处理函数,因为 addEventListener() 方法要求将函数或方法作为参数来传递。

类的枚举

“枚举”是您创建的一些自定义数据类型,用于封装一小组值。ActionScript 3.0 并不支持具体的枚举工具,这与 C++ 使用 enum 关键字或 Java 使用 Enumeration 接口不一样。不过,您可以使用类或静态常量创建枚举。例如,ActionScript 3.0 中的 PrintJob 类使用名为 PrintJobOrientation 的枚举来存储 "landscape" 和 "portrait" 值,如下面的代码所示:

public final class PrintJobOrientation 
{ 
    public static const LANDSCAPE:String = "landscape"; 
    public static const PORTRAIT:String = "portrait"; 
}

按照惯例,枚举类是使用 final 属性声明的,因为不需要扩展该类。该类仅包括静态成员,这表示不创建该类的实例。而是直接通过类对象来访问枚举值,如以下代码摘录中所示:

var pj:PrintJob = new PrintJob(); 
if(pj.start()) 
{ 
    if (pj.orientation == PrintJobOrientation.PORTRAIT) 
    { 
        ... 
    } 
    ... 
}

ActionScript 3.0 中的所有枚举类都只包含 String、int 或 uint 类型的变量。使用枚举而不使用文本字符串或数字值的好处是,使用枚举更易于发现字面错误。如果枚举名输入错误,ActionScript 编译器会生成一个错误。如果使用字面值,存在拼写错误或使用了错误数字时,编译器并不会报错。在上一个示例中,如果枚举常量的名称不正确,编译器会生成错误,如以下代码摘录中所示:

    if (pj.orientation == PrintJobOrientation.PORTRAI) // compiler error

但是,如果拼错了字符串字面值,编译器并不生成错误,如下所示:

    if (pj.orientation == "portrai") // no compiler error

创建枚举的第二种方法还包括使用枚举的静态属性创建单独的类。这种方法的不同之处在于每一个静态属性都包含一个类实例,而不是字符串或整数值。例如,以下代码为一星期中的各天创建了一个枚举类:

public final class Day 
{ 
    public static const MONDAY:Day = new Day(); 
    public static const TUESDAY:Day = new Day(); 
    public static const WEDNESDAY:Day = new Day(); 
    public static const THURSDAY:Day = new Day(); 
    public static const FRIDAY:Day = new Day(); 
    public static const SATURDAY:Day = new Day(); 
    public static const SUNDAY:Day = new Day(); 
}

ActionScript 3.0 并不使用这种方法,但是许多开发人员都使用,他们更喜欢使用这种方法提供的改进类型检查功能。例如,返回枚举值的方法可将返回值限定为枚举数据类型。以下代码不但显示了返回星期中各天的函数,还显示了将枚举类型用作类型注释的函数调用:

function getDay():Day 
{ 
    var date:Date = new Date(); 
    var retDay:Day; 
    switch (date.day) 
    { 
        case 0: 
            retDay = Day.MONDAY; 
            break; 
        case 1: 
            retDay = Day.TUESDAY; 
            break; 
        case 2: 
            retDay = Day.WEDNESDAY; 
            break; 
        case 3: 
            retDay = Day.THURSDAY; 
            break; 
        case 4: 
            retDay = Day.FRIDAY; 
            break; 
        case 5: 
            retDay = Day.SATURDAY; 
            break; 
        case 6: 
            retDay = Day.SUNDAY; 
            break; 
    } 
    return retDay; 
} 
 
var dayOfWeek:Day = getDay();

您还可以增强 Day 类的功能,使其将一个整数与一星期中的各天关联,并提供一个 toString() 方法来返回各天的字符串表示形式。

嵌入资源类

ActionScript 3.0 使用称为 嵌入资源类 的特殊类来表示嵌入的资源。 嵌入资源 指的编译时包括在 SWF 文件中的资源,如声音、图像或字体。嵌入资源而不是动态加载资源可以确保资源在运行时可用,但代价是增加了 SWF 文件的大小。

在 Flash Professional 中使用嵌入的资源类

要嵌入资源,首先将该资源放入 FLA 文件的库中。接着,使用资源的链接属性,提供资源的嵌入资源类的名称。如果无法在类路径中找到具有该名称的类,则将自动生成一个类。然后,可以创建嵌入资源类的实例,并使用任何由该类定义或继承的属性和方法。例如,以下代码可用于播放链接到名为 PianoMusic 的嵌入资源类的嵌入声音:

var piano:PianoMusic = new PianoMusic(); 
var sndChannel:SoundChannel = piano.play();

还可使用 [Embed] 元数据标签在 Flash Professional 项目中嵌入资源,如下面所述。如果在代码中使用 [Embed] 元数据标签,Flash Professional 将使用 Flex 编译器而非 Flash Professional 编译器编译您的项目。

利用 Flex 编译器使用嵌入资源类

如果您正在使用 Flex 编译器编译代码,可使用 [Embed] 元数据标签将资源嵌入到 ActionScript 代码中。将资源放置在项目生成路径中的主资源文件夹或其他文件夹中。当 Flex 编译器遇到 Embed 元数据标签时,会创建嵌入资源类。通过紧接 [Embed] 元数据标签之后声明的数据类型 Class 的变量,可以访问该资源类。例如,下面的代码嵌入名为 sound1.mp3 的声音,使用名为 soundCls 的变量来存储对该声音的关联嵌入资源类的引用。然后,该示例创建嵌入资源类的实例,并对该实例调用 play() 方法:

package 
{ 
    import flash.display.Sprite; 
    import flash.media.SoundChannel; 
    import mx.core.SoundAsset; 
 
    public class SoundAssetExample extends Sprite 
    { 
        [Embed(source="sound1.mp3")] 
        public var soundCls:Class; 
         
        public function SoundAssetExample() 
        { 
            var mySound:SoundAsset = new soundCls() as SoundAsset; 
            var sndChannel:SoundChannel = mySound.play(); 
        } 
    } 
}

Adobe Flash Builder

若要在 Flash Builder ActionScript 项目中使用 [Embed] 元数据标签,可从 Flex 框架导入所有必需的类。例如,若要嵌入声音,可导入 mx.core.SoundAsset 类。若要使用 Flex 框架,可将文件 framework.swc 包含在 ActionScript 生成路径中。这样会增加 SWF 文件的大小。

Adobe Flex

另外,在 Flex 中,通过在 MXML 标签定义中使用 @Embed() 指令也可以嵌入资源。