類和物件導向編程
類(Class)和物件導向(Object Oriented),對於有些讀者來說可能還沒接觸過而有些讀
者可能已經在 AS (或其它語言) 中使用過很多年了,為了讓大家都能學會,我會扼要的介
紹一下這些基礎知識。就算是 AS 2 的 OOP 專家也希望能略讀下這一段,因為 AS 3.0 的
只要你在 Flash 中
工作原理確實發生了很大的變化。 如果你說你從沒用過類,那你就錯了,
寫過代碼,那麼實際上就已經使用了類。類可以簡單理解為一種對象, MovieClip 就是影
片剪輯的類,而文字框、影片剪輯、按鈕、字串和數值等都有它們自己的類。
一個類最基本的兩個部分:屬性(資料或資訊),行為(動作或它能做的事)。屬性
(Property)指用於儲存與該類有關的資訊變數, 行為(Behavior)就是指函數,如果一個函數
是這個類中的一部分,那麼我們就稱它為方法(Method)。
一個基本的類:
常用 Flash 的朋友都知道,我們可以在庫中建立一個元件,用這個元件可以在舞台上
建立出很多的執行個體。與元件和執行個體的關係相同,類就是一個模板,而對象(如同執行個體)就是類
的一個特殊表現形式。下面來看一個類的例子:
package {
public class MyClass {
public var myProperty:Number = 100;
public function myMethod() {
trace("I am here");
}
}
}
先來說明一下這段代碼。在這裡有些新的知識,對於 AS 2 老手也如此:包的聲明。包
作用就是把相關的類進行分組。知道這一點就夠了,我們不再進行深入的討論,
(Package) ,
本書的樣本甚至不會用到包。Package 這個關鍵字和一對大括弧是必需有的,我們理解為默
認包,緊隨其後的就是類的定義。
另一個變化是 AS3.0 中的類擁有了訪問關鍵字。訪問關鍵字是指:一個用來指定其它代碼
是否可訪問該代碼的關鍵字。 public (公有類) 關鍵字指該類可被外部任何類的代碼訪問。
本書中所有樣本的類都是 public 的。在深入學習了 AS 3.0 後,我們會發現不是所有類都
是公有的,甚至還有多重的類,這些內容超出了本書的談論範圍。
本例中我們可以看到,這個類的名字為 MyClass,後面跟一對大括弧。在這個類中有兩
種要素,一個是名為 myProperty 的變數,另一個是名為 myMethod 的函數。
包(Package)
包主要用於組織管理類。包是根據類所在的目錄路徑所構成的,並可以嵌套多層。包名
所指的是一個真正存在的檔案夾,用 “.”進行分隔。例如,有一個名為 Utils 的類,存
在於檔案夾 com/ friendsofed/ makingthingsmove/ 中(使用網域名稱作為包名是一個不成文
的規定,目的是保證包名是唯一的)。這個類就被寫成
com.friendsofed.makingthingsmove.Utils。
在 AS 2 中,使用整個包名來建立一個類,例如:
class com.friendsofed.makingthingsmove.Utils {
}
在 AS 3 中,包名寫在包的聲名處,類名寫類的聲名處,例如:
package com.friendsofed.makingthingsmove{
public class Utils {
}
}
匯入(Import)
想象一下,每次要使用這個類的方法時都要輸入
com.friendsofed.makingthingsmove.Utils,是不是太過煩瑣太過死板了。別擔心,import
語句可以解決這個問題。在這個例子中,可以把下面這句放在 package 中類定義的上面:
import com.friendsofed.makingthingsmove.Utils;。
建構函式(Constructor)
建構函式是指一個名字與類名相同的方法。當該類被執行個體化時,該函數會被自動調用,
也可以傳入參數,例如:
首先,建立一個類:
package {
public class MyClass {
public function MyClass(arg:String) {
trace("constructed");
trace("you passed " + arg);
}
}
}
然後,假設工作在 Flash CS3 IDE(整合式開發環境)中,在時間軸上建立該執行個體:
var myInstance:MyClass = new MyClass("hello");
結果輸出:
constructed
you passed hello
繼承(Inheritance)
一個類可以從另一個類中繼承(inherit)和擴充(extend)而來。這就意味著它獲得了另
一個類所有的屬性和方法(除了那些被 private 掩蓋住的屬性)。所產生的子類(衍生類別)還
可以增加更多的屬性和方法, 或更改父類(基類)已有的屬性或方法。要分別建立兩個類來實
現(兩個獨立的 .as 檔案),例如:
package {
public class MyBaseClass {
public function sayHello():void {
trace("Hello from MyBaseClass");
}
}
}
package {
public class MySubClass extends MyBaseClass {
public function sayGoodbye():void {
trace("Goodbye from MySubClass");
}
}
}
不要忘記,每個類都必須在其自身的檔案中,檔案名稱為該類的類名,副檔名 .as,所以
必須要有 MyBaseClass.as 檔案和 MySubClass.as 檔案。 因此,在使用 Flash CS3 IDE 時,
儲存的 FLA 檔案,要與這兩個類在同一個檔案夾。
下面代碼會生產兩個執行個體,把它寫入時間軸看看會發生什麼:
var base:MyBaseClass = new MyBaseClass();
base.sayHello();
var sub:MySubClass = new MySubClass();
sub.sayHello();
sub.sayGoodbye();
第一個執行個體沒什麼可說的,值得注意的是第二個執行個體中的 sayHello 方法,雖然在
MySubClass 中沒有定義 sayHello,但它卻是繼承自 MyBaseClass 類的。另一個值得注意
的是,增加了一個新的方法 sayGoodbye,這是父類所沒有的。
下面說說,在子類中如何改變一個父類中已存在的方法。在 AS 2 中,我們可以只需要重新
定義這個方法就可以了。而在 AS 3 中,則必需明確地寫出 override 關鍵字,來進行重新
定義。
package {
public class MySubClass extends MyBaseClass {
override public function sayHello():void {
trace("Hola from MySubClass");
}
public function sayGoodbye():void {
trace("Goodbye from MySubClass");
}
}
}
請注意,原來的 sayHello 方法被重寫,再調用 MySubClass 後,就有了新的資訊。另
外,私人成員也不能被重寫,因為它們只能被它們自身的類訪問。
MovieClip/Sprite 子類
我們可以自己寫一個類,然後讓另一個類去繼承它。在 AS 3 中,所有代碼都不是寫在
時間軸上的,那麼它們一開始都要繼承自 MovieClip 或 Sprite。 MovieClip 類是影片剪
輯對象屬性和方法的 ActionScript 模板。它包括我們所熟悉的屬性如:影片的 x,y 座標,
縮放等,這些在 AS 3 中的變化不大。
AS 3 還增加了 Sprite 類,通常把它理解為不在時間軸上的影片剪輯。很多情況下,
只使用代碼操作對象,並不涉及時間軸和幀,這時就應該使用 Sprite 這個輕型的類。如果
一個類繼承自 MovieClip 或 Sprite ,那麼它會自動擁有該類所有的屬性和方法,我們還
可以為這個類增加特殊的屬性和方法。
例如,遊戲設計一個太空船的對象,我們希望它擁有一個圖形,並且在螢幕的某個位置
移動,旋轉,並為動畫添加 enterFrame 接聽程式,還有滑鼠、鍵盤的偵聽等。這些都可以由
MovieClip 或 Sprite 來完成,所以就要繼承自它們。同時,還可以增加一些屬性如:速度
(speed)、 油量(fuel)、損壞度(damage),還有像起飛(takeOff)、墜落(crash)、射擊(shoot)
或是自毀(selfDestruct)等方法。那麼這個類大概是這樣的:
package {
import flash.display.Sprite;
public class SpaceShip extends Sprite {
private var speed:Number = 0;
private var damage:Number = 0;
private var fuel:Number = 1000;
public function takeOff():void {
//...
}
public function crash():void {
//...
}
public function shoot():void {
//...
}
public function selfDestruct():void {