類別

類別是物件的抽象形式,類別會儲存有關物件可保存之資料類型以及物件所能展現之行為方式的資訊。當您撰寫小型 Script,而其中只包含彼此互動的少數幾個物件時,這種抽象觀念的用處也許不太明顯。不過,程式的範圍會讓必須管理的物件數量增加。在這個情況下,類別可以讓您更好控制物件的建立方式以及彼此的互動方式。

早在 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 陳述式,套件名稱必須包含於套件宣告中,而不是包含於類別宣告中。例如,下列類別宣告會示範,BitmapData 類別 (屬於 flash.display 套件的一部分) 如何分別在 ActionScript 2.0 和 ActionScript 3.0 中進行定義:

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

Class 特質

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 的 ActionScript 3.0 參考 」書中,這個詞彙適用的範圍較窄。就上下文來說,屬性這個詞彙只包括屬於變數的類別成員,或由 getter、setter 方法定義的類別成員。在 ActionScript 3.0 中,有一組特質可配合任何類別的屬性使用,下表列出這組特質的清單。

特質

定義

internal (預設值)

相同套件之內的參考可以看見。

private

相同類別之中的參考可以看見。

protected

相同類別及衍生類別之中的參考可以看見。

public

任何一處的參考都可以看見。

static

指定屬性屬於類別,而不屬於該類別的實體。

UserDefinedNamespace

由使用者定義的自訂命名空間名稱。

存取控制命名空間特質

ActionScript 3.0 提供四個特殊的特質,可控制類別之內所定義屬性的存取: public private protected internal

public 特質可讓屬性在您的 Script 中隨處可見。例如,若要讓方法可供套件之外的程式碼使用,您必須以 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"] ) 時的情形一樣。

下表摘要列出嘗試存取屬於密封 (而非動態) 類別之私有屬性的結果:

嚴謹模式

標準模式

點運算子 ( . )

編譯階段錯誤

執行階段錯誤

方括號運算子 ( [] )

執行階段錯誤

執行階段錯誤

在以 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

一般來說,類別之外的程式碼嘗試存取私有屬性時,動態類別會傳回值 undefined 而不會產生錯誤。下表顯示,只有使用了點運算子,在嚴謹模式中存取私有屬性時,才會產生錯誤:

嚴謹模式

標準模式

點運算子 ( . )

編譯階段錯誤

undefined

方括號運算子 ( [] )

undefined

undefined

protected 特質是 ActionScript 3.0 中新增的特質,它會讓位於屬性本身所在類別或子類別之中的呼叫者看見該屬性;也就是說,一個保護的屬性是在本身類別之內,或是對於位在其下繼承階層中任何一處的類別,才能使用,不管子類別是位於相同或不同的套件中都一樣。

至於熟悉 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 關鍵字宣告的變數可以在整個 Script 執行期間多次變更其值;以 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 實體的特定組件 (月份),直接在實體的值上運作。

由於靜態方法並不與個別實體繫結,您不能在靜態方法的主體之中使用關鍵字 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 的屬性,但其實是一對 get 和 set 存取子函數,在名為 privateProperty 的私有屬性上運作。下列範例會將 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 不會使用這項技巧,但很多開發人員喜歡這項技巧所提供的改良類型檢查,因此都會加以利用。例如,傳回列舉值的方法可以將傳回值限定於 enumeration 資料類型。下列程式碼不但示範會傳回星期別的函數,也示範使用列舉類型做為類型附註的函數呼叫:

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 編譯器編譯自己的程式碼,要在 ActionScript 程式碼中嵌入一個資源,請使用 [Embed] 中繼資料標籤。將資源放在主要來源資料夾或專案組建路徑中的其他資料夾。當 Flex 編譯器遇到 Embed 中繼資料標籤時,就會為您增加內嵌資源類別。您可以透過資料類型 Class 的變數存取類別,變數必須在 [Embed] 中繼資料標籤之後立即宣告。例如,下列程式碼嵌入稱為 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 架構,請在 ActionScript 組建路徑中包含 framework.swc 檔案。這樣會增加 SWF 檔的大小。

Adobe Flex

或者,在 Flex 中,您也可以在 MXML 標籤定義中使用 @Embed() 指令內嵌資源。