Flash CS3 文件 |
|||
| ActionScript 3.0 程式設計 > ActionScript 語言和語法 > 資料類型 > 類型檢查 | |||
類型檢查可能會在編譯階段或執行階段發生。靜態產生類型的語言 (如 C++ 和 Java) 會在編譯階段進行類型檢查;動態產生類型的語言 (如 Smalltalk 和 Python) 會在執行階段處理類型檢查。ActionScript 3.0 是動態產生類型的語言,具有執行階段類型檢查功能,但也能以特殊的編譯器模式 (稱為「嚴謹模式」) 支援編譯階段類型檢查功能。在嚴謹模式中,類型檢查會在編譯器階段及執行階段發生;但是在標準模式中,類型檢查只在執行階段中發生。
動態產生類型的語言能在建構程式碼時提供極大的彈性,但是卻必須允許類型錯誤在執行階段顯現。靜態產生類型的語言會在編譯階段報告類型錯誤,但是在編譯階段就必須要知道類型資訊。
大型專案經常偏好使用編譯階段類型檢查,因為隨著專案的大小成長,資料類型彈性通常變得比較不重要,反而是盡可能早發現類型錯誤更重要。因此才會根據預設,將 Adobe Flash CS3 Professional 和 Adobe Flex Builder 2 中的 ActionScript 編譯器設定為在嚴謹模式中執行。
為了提供編譯階段類型檢查,編譯器必須知道程式碼中變數或運算式的資料類型資訊。若要明確地宣告變數的資料類型,請加入冒號運算子 (:),之後再用資料類型做為變數名稱的字尾。若要使資料類型與參數產生關聯,請使用冒號運算子,之後再加上資料類型。例如,下列程式碼會將資料類型資訊加入 xParam 參數,而用明確的資料類型宣告變數 myParam:
function runtimeTest(xParam:String)
{
trace(xParam);
}
var myParam:String = "hello";
runtimeTest(myParam);
在嚴謹模式中,ActionScript 編譯器會將類型不相符回報為編譯器錯誤。例如,下列程式碼會宣告 Object 類型的函數參數 xParam,但稍後會嘗試將 String 和 Number 類型的值指定給該參數。如此會在嚴謹模式中產生編譯器錯誤。
function dynamicTest(xParam:Object)
{
if (xParam is String)
{
var myStr:String = xParam; // 嚴謹模式中的編譯器錯誤
trace("String: " + myStr);
}
else if (xParam is Number)
{
var myNum:Number = xParam; // 嚴謹模式中的編譯器錯誤
trace("Number: " + myNum);
}
}
但是,即使在嚴謹模式中,您也可以選擇性地將指定陳述式的右邊保留為不具類型,決定不執行編譯階段類型檢查。您可以省略類型註釋,或使用特殊的星號 (*) 類型註釋,讓變數或運算式成為不具類型。例如,若上一個範例中的 xParam 參數已經過修改,使它不再有類型註釋,則程式碼將在嚴謹模式中進行編譯:
function dynamicTest(xParam)
{
if (xParam is String)
{
var myStr:String = xParam;
trace("String: " + myStr);
}
else if (xParam is Number)
{
var myNum:Number = xParam;
trace("Number: " + myNum);
}
}
dynamicTest(100)
dynamicTest("one hundred");
無論您在嚴謹模式或標準模式中進行編譯,ActionScript 3.0 中都會發生執行階段類型檢查。請考慮一種情況,在此情況下,3 這個值是傳遞做為預期有陣列的函數之引數。在嚴謹模式中,編譯器將產生錯誤,因為 3 這個值與資料類型 Array 不相容。若停用嚴謹模式,而且在標準模式中執行,則編譯器會回報類型不相符,但由 Flash Player 執行的執行階段類型檢查則會導致執行階段錯誤。
下列範例會顯示名為 typeTest() 的函數,它預期會收到 Array 引數,但收到的卻是 3 這個值。如此便會在標準模式中導致執行階段錯誤,因為 3 這個值並不是該參數之宣告資料類型 (Array) 的成員。
function typeTest(xParam:Array)
{
trace(xParam);
}
var myNum:Number = 3;
typeTest(myNum);
// ActionScript 3.0 標準模式中的執行階段錯誤
也可能會有一些情況,在這些情況下您會收到執行階段錯誤,甚至在嚴謹模式中操作時也一樣。如果使用嚴謹模式,但使用不具類型變數,決定不執行編譯階段類型檢查,就可能會發生這種情況。當您使用不具類型的變數時,並不會消除類型檢查,而是將檢查延遲到執行階段再進行。例如,假設上一個範例中的 myNum 變數並未宣告資料類型,編譯器無法偵測類型不相符的情形,但 Flash Player 將產生執行階段錯誤,因為它會比較 myNum 的執行階段值 (由於指定陳述式的結果而設定為 3) 與 xParam 的類型 (設定為 Array 資料類型)。
function typeTest(xParam:Array)
{
trace(xParam);
}
var myNum = 3;
typeTest(myNum);
// ActionScript 3.0 中的執行階段錯誤
相較於編譯階段檢查,執行階段檢查也允許能以更具彈性的方式使用繼承。藉由將類型檢查延遲到執行階段,即使您「向上轉型」,標準模式也可以讓您參考子類別的屬性。使用基底類別宣告類別實體的類型,而用子類別進行實體化時,就會發生向上轉型。例如,您可以建立可擴充的 ClassBase 類別 (具有 final 特質的類別無法進行擴充):
class ClassBase
{
}
接著,您可以建立 ClassBase 的子類別 ClassExtender,它具有一個 someString 屬性,如下所示:
class ClassExtender extends ClassBase
{
var someString:String;
}
您可以使用這兩個類別,建立使用 ClassBase 資料類型宣告的類別實體,但使用 ClassExtender 建構函式進行實體化。向上轉型被視為安全作業,因為基底類別只包含子類別中的屬性或方法。
var myClass:ClassBase = new ClassExtender();
但是子類別確實包含基底類別所不包含的屬性或方法。例如,ClassExtender 類別包含 someString 屬性,而 ClassBase 類別中並沒有此屬性。在 ActionScript 3.0 標準模式中,您可以使用 myClass 實體參考此屬性,而不會產生編譯階段錯誤,如下列範例所示:
var myClass:ClassBase = new ClassExtender(); myClass.someString = "hello"; // ActionScript 3.0 標準模式中沒有錯誤
is 運算子是 ActionScript 3.0 新增的運算子,可以讓您測試變數或運算式是否為指定資料類型的成員。在舊版 ActionScript 中,是由 instanceof 運算子提供此功能,但在 ActionScript 3.0 中,則不應該使用 instanceof 運算子來測試資料類型的成員資格。進行手動類型檢查時,請勿使用 instanceof 運算子,而應該改用is 運算子,因為運算式 x instanceof y 只會檢查 x 的原型鏈是否有 y 存在 (而在 ActionScript 3.0 中,原型鏈並不提供完整的繼承階層狀況)。
is 運算子會檢查正確的繼承階層,且不但可用來檢查物件是否為特定類別的實體,並可用來檢查物件是否為實作特定介面的類別實體。下列範例會建立名為 mySprite 的 Sprite 類別實體,並使用 is 運算子測試 mySprite 是否為 Sprite 和 DisplayObject 類別的實體,以及它是否會實作 IEventDispatcher 介面:
var mySprite:Sprite = new Sprite(); trace(mySprite is Sprite); // true trace(mySprite is DisplayObject); // true trace(mySprite is IEventDispatcher); // true
is 運算子會檢查繼承階層,並正確報告 mySprite 與 Sprite 和 DisplayObject 類別相容 (Sprite 類別是 DisplayObject 類別的子類別)。is 運算子也會檢查 mySprite 是否繼承自任何實作 IEventDispatcher 介面的類別。由於 Sprite 類別是繼承自 EventDispatcher 類別,此類別會實作 IEventDispatcher 介面,所以 is 運算子會正確報告 mySprite 實作相同的介面。
下列範例會示範上個範例的相同測試,但是使用的是 instanceof 而不是 is 運算子。instanceof 運算子會正確地識別 mySprite 為 Sprite 或 DisplayObject 的實體,但在用來測試 mySprite 是否實作 IEventDispatcher 介面時,則會傳回 false。
trace(mySprite instanceof Sprite); // true trace(mySprite instanceof DisplayObject); // true trace(mySprite instanceof IEventDispatcher); // false
as 運算子是 ActionScript 3.0 新增的運算子,也可以讓您檢查運算式是否為指定資料類型的成員。與 is 運算子不同,as 運算子不會傳回 Boolean 值。as 運算子是傳回運算式的值而非 true;傳回 null 而非 false。下列範例會示範不使用 is 而改用 as 運算子,在簡單的範例中檢查 Sprite 實體是否為 DisplayObject、IEventDispatcher 和 Number 資料類型的成員所得出的結果。
var mySprite:Sprite = new Sprite(); trace(mySprite as Sprite); // [object Sprite] trace(mySprite as DisplayObject); // [object Sprite] trace(mySprite as IEventDispatcher); // [object Sprite] trace(mySprite as Number); // null
當您使用 as 運算子時,右邊的運算元必須是資料類型。若嘗試在右邊使用運算式而不用資料類型做為運算元,將會導致錯誤。
Flash CS3
目前頁面: http://livedocs.adobe.com/flash/9.0_tw/main/00000045.html