日期:2013-1-17 浏览次数:20153次 点赞次数:20

aiyiweb核心提示:面向对象的难点部分就是理解变量作用域修饰符(modifier)其实也就是面向对象中我们曾经熟悉的public、protected、private等等。本文还深入讨论了ActionScript3中新增的internal等概念。

本文是我在整理了相关文档和讨论之后,结合本人的亲身实验总结出来的一些经验和心得。我尽量描述详尽,避免模糊概念,当然也希望所有看官提出批评意见。为了表述方便,其中术语不限定言语,如我可能会一会儿用class,一会儿用“类”。

面向对象的难点部分就是理解变量作用域修饰符(modifier)其实也就是面向对象中我们曾经熟悉的public、protected、private等等。本文还深入讨论了ActionScript3中新增的internal等概念。

下面我顺次列出:

一、关于package以及internal
package,用“形而上学”的方式理解,就是物理目录下的类集合。在AS2中只需求保证文件系统的路径婚配,然后用类似“import com.awflasher.someUtils”的方法导入即可。而AS3则要求您在所有的类中声明package关键词。package的大括号对 “{}”内,我们只能定义一个类,我们可以在这个大括号外面定义一些辅助类,不过这些类只能被当前这个类(你在package大括号对内定义的类)访问。当然,一个package大括号对内只要一个类,这并不代表一个package内只要一个类。你可以在同一目录下定义多个属于该package(指代这个目录)的类。它的意义绝不是简单的“类文件集合容器”,而是一个让各种应该协同任务的类集中到一同的项目包。值得一提的是,所谓“协同任务”是指至少有一个class要引入其他一些class 来进行功用设计,而这时候采用internal修饰可以省去很多getters和setters。我本人回忆起在湖南卫视的项目中用AS2开发的 Vplayer,两个类AVCore和AVControl就有很多getter和setter,搞的特别麻烦。

internal类似public,但限定在一个 package内了。在同一个package内的类可以访问同一个package内其他类的internal变量,而其他包内的类无法访问。 package 与类的承继性毫无关系,比如TextField和Sprite、MovieClip都承继自DisplayObject类,但TextField属于 flash.text包,而MovieClip和Sprite属于flahs.display包。也就是说,包对类的限定是与承继链毫无关联的、一个新的 “维度”的限定。
附:使用一个类的时候,我们必须import这个类,或者包含这个类的package。AS2时直接写完整包路径的使用方法在AS3中不管用了,本文后面有详细引见。

二、关于public
public定义的类或者属性可以在任何作用域内由任何来源访问。结构函数永远都是public的,Flex中的使用程序类(Application Class)和Flash CS3中的文档类(Document Class)必须是public的。且不能缺省public这个关键词声明。我在测试中发现,如果不声明public,Flash基本就不会获取类的定义,进而编译无法通过。

三、关于protected
protected声明类似AS2的private,它定义的属性只能在本人子类中可见,而其它场合都是不可见的。这一点与Java等传统OOP言语类似。

四、关于private
留意AS3的private和AS2的private大不相反,它定义的属性只属于本人,子类可以定义毫无牵连的同名属性。
dynamic 和原来AS2的dynamic一样,用dynamic声明的类可以动态的加入属性。这些属性也可以通过delete来删除。动态加入的属性一旦被切断所有的援用就会被垃圾回收机制自动回收。有时候用System.totalMemory检测不到内存释放是由于垃圾回收机制并不是即时运转的。

五、关于dynamic
动态(dynamic)类允许在运转时动态地添加属性,常见的动态类有MovieClip和顶级(top-level)的Array。如果您的自定义类要承继于动态类,那么请也定义为动态的,不要省略dynamic关键词。

六、关于承继(extends)和override
承继其实并不太复杂,独一要说明的就是:子类的结构函数一定要用“super”调用一次父类的结构函数,否则报错!对于承继后的子类,如果要重新定义父类的非private方法,必须使用override关键词。在override的时候,如果我们需求调用父类的方法,可以使用super关键词(由于承继方法在逻辑上与父类往往有类似性,因此没有必要把方法逻辑完全重写)官方协助中的这个例子非常易懂:
package {
import flash.display.MovieClip;
public class SuperExample extends MovieClip
{
public function SuperExample()
{
var myExt:Extender = new Extender()
trace(myExt.thanks()); // output: Mahalo nui loa
}
}
}

class Base {
public function thanks():String
{
return “Mahalo”;
}
}

class Extender extends Base
{
override public function thanks():String
{
return super.thanks() + ” nui loa”;
}
}

override不能用于重载变量(成员属性)。但是却可以用于重写getter和setter函数,例如:(官方协助的例子)
package
{
import flash.display.MovieClip;
public class OverrideExample extends MovieClip
{
public function OverrideExample()
{
trace(currentLabel)
}
override public function get currentLabel():String
{
var str:String = “Override: “;
str += super.currentLabel;
return str;
}
}
}

这个例子中,我们直接重写了MovieClip类的currentLabel属性。留意调用父类属性的时候,用了super.currentLabel。

关于静态方法,比较麻烦。首先,静态方法是无法被重载的。必须通过类来访问。但是您也可以本人定义与静态方法同名的方法,我把官方的例子做了一下修正就了如指掌了:

package
{
import flash.display.MovieClip;
public class StaticExample extends MovieClip
{
public function StaticExample()
{
var myExt:Extender = new Extender();
}
}
}

class Base {
public static var test:String = “static”;
}

class Extender extends Base
{
private var test:String = “instance”;<