ActionScript 3 Cookbook 中文版 第二章. 自定义类

来源:互联网 发布:电视看最新电影软件 编辑:程序博客网 时间:2024/05/16 14:54

ActionScript 3 Cookbook 中文版

第二章. 自定义类
第 1 页 共 17 页
第二章. 自定义类
2.0. 简介
2.1. 创建自定义类
2.2. 类的保存
2.3. 创建成员属性
2.4. 创建静态方法或属性
2.5. 创建子类
2.6. 覆盖父类方法
2.7. 创建常量
2.8. 发送事件
ActionScript 3 Cookbook 中文版
第二章. 自定义类
第 2 页 共 17 页
2.0.简介
ActionScript 3.0 最本质的东西就是类,也就说它是面向对象的。 ActionScript 3.0 在面向对象基础
上重新构建了ActionScript 核心。如果在Flex上编写ActionScript 3.0,代码都被放在<mx:Script> 标
签内,所有ActionScript 都必须以类的形式出现。这一章讨论在ActionScript 3.0 上编写自定义类。
ActionScript 3 Cookbook 中文版
第二章. 自定义类
第 3 页 共 17 页
2.1. 创建自定义类
问题
我要编写自己的类
解决办法
保存一个以.as 扩展名的新文件,类名和文件名相同,编写如下结构:
package package {
public class Class {
}
}
讨论
在ActionScript 3 中,类是最基本的编程结构,所以必须先掌握编写类的基础知识。对于初学者,
所以得类都必须放在.as文件中,每个as文件里只能定义一个public 类,而且类名字要与文件名相
同。比如:你的类名为 Example ,那么文件名必须为 Example.as.
在 ActionScript 3.0 中所有的类都必须放在包中。包是对类进行分类的单位,其意义相当于文件系
统的目录。包路径相对于classpath(类路径),默认的类路径就是项目的根目录(就是包含mxml
文件的所在目录),因此顶级的包目录就是项目根目录。包申明如下:
package name {}
如果类定义在顶级包中,那么包名可以不指定,如:
package {}
当类文件保存在子目录,那么包名就是它的保存目录,例如,文件保存在example 目录,那么包这
样申明:
package example {}
如果类文件保存在 example 目录的子目录 subpackage, 应这样申明:
package example.subpackage {}
包是很重要的,它可以避免类名称空间冲突。例如,有两个开发者写了两个类文件都叫
MessageManager. 这两个类虽有相同名字,但是完成不同的任务,因此你不能把这两个类放在一
起,如果这样做,编译器将不知道调用哪个,一个办法是取个唯一的类名字。
你可以取名字叫 EmailManager 和 BinarySocket- MessageManager, 这是可以的,但是如果你管
理成千上万的类这时就很困难了。因此用包可以很好的解决这个问题,即使你有很多相同的类名,
只要它们不在同一个包就不会冲突,如把 MessageManager 放在net.messaging.email 包另一个
放在net.messaging.binarysocket 包中。
ActionScript 3 Cookbook 中文版
第二章. 自定义类
第 4 页 共 17 页
一般取包名都以自己的网站域名,这样可以最大限度避免和别人的包名相冲突。
当有多个项目公用一些类,那么这些类直接被放在主包 中的子目录中。例如,上面的
MessageManager 类放在com.examplecorp.net.messaging.email 和
com.examplecorp.net.messaging.binary- socket 包中。
下一步就是申明类自身:
public class Name {
}
类申明必须在包内。下面的代码在顶级包中定义了叫 Example 的类:
package {
public class Example {
}
}
类主体在括号内定义,包括属性,方法。属性就是和类关联的变量,使用var 关键字申明他们,属
性也有修饰符指定其范围。修饰符有:
private
该属性只有类实例自身可访问.
public
该属性可以被任何类实例访问(若直接被类访问可设置成static)
protected
该属性只被自身类实例或派生类实例访问。
Internal
该属性可被包内的类实例访问。
默认情况下是属性被指定为 internal ,除非自己指定修饰符。大多数情况,属性被指定为 private 或
protected。按照习惯约定,private 和 protected 申明的属性名称都在前面加上下划线。看下面的
例子:
package {
public class Example {
private var _id:String;
}
}
与类关联的还有方法,你可以使用function 关键字像申明函数那样申明方法。和属性一样,方法也
有修饰符(public, private, protected, internal)。如果方法被类实例访问可设置为public(直接被类
访问则加上static).如果方法只在类内方法则被设置为 private 或 protected。下面的代码申明一个
方法叫getId( ):
ActionScript 3 Cookbook 中文版
第二章. 自定义类
第 5 页 共 17 页
package {
public class Example {
private var _id:String;
public function getId( ):String {
return _id;
}
}
}
按照约定,方法名称的起始字符必须为小写。每个类都有个和自己类名相同的方法,该方法称为构
造函数,用它为创建新的实例时进行初始化工作。在 ActionScript 3.0 中,所有的构造函数都是
public ,不像标准的方法,构造函数不能有返回值,也不能申明有返回类型。下面的代码申明了构造
函数:
package {
public class Example {
private var _id:String;
public function Example( ) {
_id = "Example Class";
}
public function getId( ):String {
return _id;
}
}
}
下面展示如何构造一个新的 Example 类实例:
var example:Example = new Example( );
trace(example.getId( )); // 显示: Example Class
ActionScript 3 Cookbook 中文版
第二章. 自定义类
第 6 页 共 17 页
2.2. 类的保存
问题
把类文件保存到哪里呢
解决办法
保存与包名称相符的目录中。
讨论
类文件保存在与包路径相符的目录中,比如:
com.examplecorp.net.messaging.email.MessageManager
必须保存在 com/examplecorp/net/messaging/email/ 目录下.
编译器就知道去哪里找类。还有编译器也必须知道根目录是什么。例如,编译器需要知道 com 目
录在哪里,编译器是通过classpath来找到com 目录。默认的classpath就是Flex或Flash项目的
根目录。例如,如果com 目录和.fla 文件或mxml 文件的同一目录,编译器就能找到这些类。其实
你也可以保存到其他目录,例如,如果你有个公共库被多个项目使用,难道要拷贝多份到每个项目
中,其实你可以编辑项目中的classpath来加入该库,这样不需要拷贝就能找到你的自定义类了。
右键点击工程名,选择Properties,选择Build Path,在Source Path 中添加和修改classpath 就可
以了。如果你只使用SDK,那么当编译项目时必须设置classpath。使用mxmlc (Flex SDK中包含
的命令行编译器), 加上 -source-path 选项, 跟上类目录,例如:
mxmlc -source-path . C:\libraries ExampleApplication.as
ActionScript 3 Cookbook 中文版
第二章. 自定义类
第 7 页 共 17 页
2.3. 创建成员属性
问题
我要创建public 成员属性
解决办法
使用隐含 getters 和 setters.
讨论
正如2.1节中所说的那样属性应该被申明为 private 或 protected。 public 属性并不是什么好主意,
因为他不能体现封装性。要尽量做好封装,这意味着类不能暴露他的内部细节,public 属性使开发
者能轻易破坏类或类实例。下面的简单例子是用了Public 属性:
package {
public class Counter {
public var count:uint;
public function Counter( ) {
count = 0;
}
}
}
构造一个Counter 实例, 然后改变count 属性值,如:
var counter:Counter = new Counter( );
counter.count++;
但是,如果count属性被规定不能超过100,那么外部修改很可能无法保证,这样破坏了这个规定,
一个办法就是设置 getters 和 setters,如下:
ActionScript 3 Cookbook 中文版
第二章. 自定义类
第 8 页 共 17 页
package {
public class Counter {
private var _count:uint;
public function Counter( ) {
_count = 0;
}
public function getCount( ):uint {
return _count;
}
public function setCount(value:uint):void {
if(value < 100) {
_count = value;
}
else {
throw Error( );
}
}
}
}
另一个办法就是用隐式getters 和 setters. 隐式 getters 和 setters 就像申明方法那样,但是看起
来又像属性getter 语法如下:
public function get name( ):Datatype {
}
setter 语法:
public function set name(value:Datatype):void {
}
ActionScript 3 Cookbook 中文版
第二章. 自定义类
第 9 页 共 17 页
下面定义隐式 getter 和 setter 方法:
package {
public class Counter {
private var _count:uint;
public function Counter( ) {
_count = 0;
}
public function get count( ):uint {
return _count;
}
public function set count(value:uint):void {
if(value < 100) {
_count = value;
}
else {
throw Error( );
}
}
}
}
counter.count = 5;
trace(counter.count);
ActionScript 3 Cookbook 中文版
第二章. 自定义类
第 10 页 共 17 页
2.4. 创建静态方法或属性
问题
我要创建的方法和属性不需要类实例就能直接访问。
解决办法
使用static 修饰符申明属性或方法
讨论
默认下属性和方法是属于实例的,例如 Example 类定义了 _id 属性和 getId( ) 方法,那么每个
Example 实例都有自己的_id 属性和getId( ) 方法。但是有种情况你希望属性或方法是和类相关联
而不是类实例,也就说不管有多少个类实例,都只有一个公共属性或方法,这样的属性和方法称为
静态属性和方法。
Flash 播放器的类中就有些这样的例子,比如 Math 类中定义了 round( ) 方法,round( ) 方法就是
个静态方法,因此可以通过类直接访问:
trace(Math.round(1.2345));
Math 类包含全部是静态方法,但是类也可以同时含有静态方法和实例方法及属性。比如 String 类
有多数实例属性和方法,然而fromCharCode( ) 方法是静态的,该方法返回字符码。
下面的代码申明了一个静态的私有的属性_example:
static private var _example:String;
修饰符的顺序没有关系,比如static private 和 private static 是一样的.
static 最重要的用处就是在单态模式下,即类只能创建一个实例,单态类有一个private static 属性
用来存储类实例,然后在一个 public static 方法中访问这个实例。
ActionScript 3 Cookbook 中文版
第二章. 自定义类
第 11 页 共 17 页
2.5. 创建子类
问题
我要创建派生类
解决办法
使用extends关键字继承已有的类
讨论
如果新建的类和已有的类拥有公共特性但是又比已有类有更多细节,这时去重写所有的代码还不如
从已有类中继承公共特性再添加专有代码。这时这个新类就是已有类的一个子类。
使用extends关键继承超类:
public class Subclass extends Superclass
子类可以引用任何超类中的 public 或 protected 的属性和方法,private 属性和方法是不能够访问
的。
继承性是非常强大的功能,但是另一方面如何正确的使用继承也很重要。在写子类之前你要确定新
类和超类是否已经有子类关系,这里有两种基本关系类型:继承和组合。你经常要确定类之间是"is a"
关系还是"has a" 关系:
"Is a" 关系是继承关系。如一个应用程序管理着一个图书馆的藏书。
"Has a" 关系是组合关系。大多数类使用组合,而且比继承更有伸缩性(然而需要更多代码)。例如
一本书不是一个作者,但是它有一个作者。
图书馆有不同类型的藏品包括书和DVDs。很明显书和DVDs 有不同的类型数据。书包括页数和作
者,而DVDs 则有播放时间数,演员,导演等等,但是也有一些公共数据,比如所有图书馆都有用
一些唯一的数字编号或命名规则来管理这些藏品. 而且每个种类都有标题或名称,这时你可以定义
个类来归纳这些公共信息:
ActionScript 3 Cookbook 中文版
第二章. 自定义类
第 12 页 共 17 页
package org.examplelibrary.collection {
public class LibraryItem {
protected var _ddc:String;
protected var _id:String;
protected var _name:String;
public function LibraryItem( ) {}
public function setDdc(value:String):void {
_ddc = value;
}
public function getDdc( ):String {
return _ddc;
}
public function setId(value:String):void {
_id = value;
}
public function getId( ):String {
return _id;
}
public function setName(value:String):void {
_name = value;
}
public function getName( ):String {
return _name;
}
}
}
ActionScript 3 Cookbook 中文版
第二章. 自定义类
第 13 页 共 17 页
书和DVDs 都是LibraryItem 的一个种类. 接下来很自然就是定义Book 类和 DVD 类,继承自
LibraryItem,Book 类类似于:
package org.examplelibrary.collection {
import org.examplelibrary.collection.LibraryItem;
public class Book extends LibraryItem {
private var _authors:Array;
private var _pageCount:uint;
public function Book( ) {}
public function setAuthors(value:Array):void {
_authors = value;
}
public function getAuthors( ):Array {
return _authors;
}
public function setPageCount(value:uint):void {
_pageCount = value;
}
public function getPageCount( ):uint {
return _pageCount;
}
}
}
默认下可以继承任何类,但是如果你不要这个类再被继承,可以添加final 修饰符申明该类:
final public class Example
ActionScript 3 Cookbook 中文版
第二章. 自定义类
第 14 页 共 17 页
2.6. 覆盖父类方法
问题
我要对从父类继承过来的方法进行重新实现。
解决办法
父类的方法必须申明为public 或 protected。当申明子类的实现时使用 override 修饰符
讨论
通常子类继承父类的所有方法而不做任何修改,但有些情况,继承过来的方法需要重新申明,实现
与父类的方法不同。这时就要覆盖方法,该方法必须加上override 修饰符。如下面的例子,首先定
义一个父类Superclass:
package {
public class Superclass {
public function Superclass( ) {}
public function toString( ):String {
return "Superclass.toString( )";
}
}
}
下一步,定义Subclass 继承自Superclass:
package {
public class Subclass extends Superclass {
public function Subclass( ) {}
}
}
默认情况下,Subclass 继承 Superclass 实现的toString( ) 方法:
var example:Subclass = new Subclass( );
trace(example.toString( )); // 显示: Superclass.toString( )
如果你要 toString( ) 方法返回不同的值,就要覆盖它,如下:
package {
public class Subclass extends Superclass {
public function Subclass( ) {}
override public function toString( ):String {
return "Subclass.toString( )";
}
}
}
ActionScript 3 Cookbook 中文版
第二章. 自定义类
第 15 页 共 17 页
覆盖方法,则该方法必须与父类的方法完全相同,包括参数数量和类型及返回类型,如果不一致,
编译器就会报错。
有时你要覆盖方法是为了实现完全不同的功能,但有时你只是要增加一些东西,这时你可以调用父
类方法:
super.methodName( );
ActionScript 3 Cookbook 中文版
第二章. 自定义类
第 16 页 共 17 页
2.7. 创建常量
问题
我要怎么申明常量
解决办法
和申明属性差不多,只是在前面多了const 关键字
讨论
常量的值一旦定义就不可改变,这在有时候是很有用的。比如你有个复合的值需要经常用到,这时
就可以把它当作简单的标示直接引用。Math.PI 就是个常量,MouseEvent.MOUSE_UP也是常量,
包含mouseUp值,设定这些常量可以减少出错,比如下面的代码错误你难以觉察出来:
// 下面的代码没错,但是mouseUp 被写成了 mousUp,因此该代码无效。
addEventListener("mousUp", onMouseUp);
但是使用常量,编译器就会给出错误提示:
// 导致编译器错误
addEventListener(MouseEvent.MOUS_UP, onMouseUp);
常量也可以有static 和public 修饰符,这时常量一申明就要赋值:
static public const EXAMPLE:String = "example";
按照约定,常量都要大写,这样可以和其他变量或属性区别开来。
ActionScript 3 Cookbook 中文版
第二章. 自定义类
第 17 页 共 17 页
2.8. 发送事件
问题
我要发送事件
解决办法
继承 flash.events.EventDispatcher 然后调用 dispatchEvent( ) 方法
讨论
事件在对象之间的通讯起到至关重要的作用,有了它才能开发出功能强大的系统。Flash Player 9, 的
flash.events.EventDispatcher类有一套事件发送机制。所有的事件都继承自EventDispatcher (比如
NetStream and Sprite). 如果你要定义个类要发送事件也要继承EventDispatcher,如:
package {
import flash.events.EventDispatcher;
public class Example extends EventDispatcher {
}
}
EventDispatcher 类有个公共方法addEventListener( ) 和 removeEventListener( ), 通过它的子
类来注册事件监听。 EventDispatcher 还有个 protected 方法 dispatchEvent( ) 来发送事件。
dispatchEvent( ) 方法至少需要flash.events.Event 对象或Event 的子类作为参数。
原创粉丝点击