Flash 的 ActionScript 3 (AS3) 是以 Java 語言為基礎, 採用物件導向(Object Oriented)的概念。
但 Flash 更有彈性, 以務實為原則, 不堅持難懂的理論, 先舉出其與 Java 語言最大的不同:
(1)Flash 物件的屬性(Property; attribute)可以在創建物件之後任意添加(即動態增加),
這更貼近真實世界, 因為你昨天沒有鬍子並不代表今天沒有鬍子:-)
Java語言則不可以在執行階段 (Rum time)動態增加物件的屬性。
(2)Flash 註冊事件監聽器(Event Listener)的方法與Java語言不同!!
Java 註冊時的參數只有一個, 是一個物件(Object), 該物件所屬的類別內有一個至很多個處理事件的函數!
當然該多個處理事件函數各自處理不同事件, 但是是屬於相關的事件(合起來是某類, 例如滑鼠類的事件)
也因為這樣, 註冊申請監聽的"命令"有一大堆 .addXXXListener( ) 函數,
這裡的XXX 代表某類(class)事件, 例如想要註冊處理滑鼠類事件(MouseEvent),
假設要監控的物件是 big_btn 這按鈕, 寫法是 big_btn.addMouseListener(有處理滑鼠事件之類別的實體);
Flash 簡化了事件處理模式, 規定每次註冊只能針對一個事件, 且是指定處理函數!
而且一招走遍天下, 只有一句註冊命令:
被監控物件.addEventListener(事件, 函數);
例如:
big_btn.addEventListener(MouseEvent.CLICK, her); // big_btn 被滑鼠按一下則請 her(){} 處理
funtciotn her(e: MouseEvent) {
trace(""+ e.target.name + " 被滑鼠按了一下"); // 印在開發時期主控台面板
//... 做事
} // her(
這裡的函數 her( ) 平時不會做事, 只有在 big_btn 被滑鼠按一下才會動起來。
因為註冊被簡化了, 如果你希望滑鼠滑入 big_btn 也要做事情, 那必須再註冊一次, 例如:
big_btn.addEventListener(MouseEvent.MOUSE_OVER, you);
這裡的 you 與上面的 her 類似, 都是獨立函數(function; 函式; 又叫method方法), 如果你認為這樣
太多個函數(請太多外勞或找來太多小弟?), 那也可把該滑鼠滑入的事件也註冊給 her( )一起處理 :
big_btn.addEventListener(MouseEvent.MOUSE_OVER, her);
但是, 這樣一來你的 her( ) 必須要辨認到底是滑入(MOUSE_OVER)還是被按一下(MouseEvent.CLICK);
這是真實世界能者多勞的概念, 一個人可以做很多事, 一個函數當然也可以做很多事, 通常是根據不同狀況做不同事,
可以利用 if 測試條件或是利用switch case 敘述做更多的判斷; 還好, 這也很簡單, 因為系統會把事件(Event)傳入
函數 her( ), 所以才要寫 function her(e: MouseEvent) { 這頭部, 小括號內就是系統傳過來
的參數(parameter), 在her( )的程式碼中就可以從傳過來的 e 這事件找出需要的資訊, 包括 e.target 是發生此事件的物件,
因為 her( ) 這函數也可能被要求要同時要監控其它的按鈕(或其它物件)的某幾種事件。
至於 Java 的事件監聽模式規範比較嚴謹, 對於初學者常搞不清楚, 但等你弄懂了卻又覺得它很有道理,
如果你急著想知道更多關於 Java 事件監聽的用法, (或是原來學 Java 沒有很認真聽現在忽然想認真了解)
可以點這跳到後面看Java 註冊事件監聽的用法(看完可以點視窗左上角的回到這)。
物件導向概念(Object Oriented Concept)
物件導向(Object Oriented)主要是類比於實際世界的物件(Object),例如汽車是一種類別(Class),
房車與跑車都是一種汽車, 表示房車是汽車做了一些修改或擴充(extends)的新類別, 跑車也是汽車做了一些修改或擴充(extends),
所以房車和跑車都是繼承(inherits)自汽車的類別, 或說房車與跑車都是 extends 汽車, 都是從汽車擴充(extends)而來!
物件(Object)有時與類別(Class)被混為一談, 例如某人說:"請幫我設計一個 ??? 的物件", 其實他的意思應該是
要說"請幫我設計一個 ??? 的類別(class)"才對, 關於物件與類別的討論稍後再說。
請注意, 有些電腦語言雖然提供物件設計與使用概念, 但是不提供把已經寫好的物件類別"擴充"(extends, 即繼承inherits),
則該語言不是物件導向(Object Oriented), 只是以物件為基礎的語言(Object Based Language)。
真正的物件導向應該包括以下四大特性:
(1)封裝 Encapsulation: 把資料(data)與跟該些 data 有關的函數(function)或方法(method)封裝到一個類別(class)內
這與真實世界很類似, 鬧鐘裡面有許多元件, 各元件有其功能(function; 沒錯, 功能的英文也是function),
全部被封裝在一起變成一個產品, 只露出給我們看的以及給我們按的按鈕或旋鈕。
(2)資訊隱藏 Information hiding(data hiding): 只有類別內的函數或方法可以存取物件內私密的資料(private data)
這更是類比於真實世界, 想一想你要設定鬧鐘會把鬧鐘拆開用手去撥動其指針嗎? 你需要動到其內部的電子零件嗎?
所以設計物件的類別時有個重要原則: 資料(屬性)儘量藏起來(hide), 函數(功能)儘量公開讓外界使用!
意思是資料儘量用 private 修飾語隱藏在內部, 只有內部的函數可以存取它,
函數則儘量用 public 修飾語開放給外部直接使用, 所以鬧鐘外表有一些按鈕或旋鈕。
(3)繼承 Inheritance 或 擴充 extends : 可以把舊的類別擴充成新的類別, 可增刪資料成員與函數成員
這概念很重要, 所以等一下我們用"動物與植物都是生物!"來詳細解釋。
(4)多型 Polymorphism : 以基底類別(base class)的指標(C++的pointer)或參考(reference)操作衍生類別(derived class)的物件
這比較難理解, 假設 Dog 和 Cat 都是 Animal(動物)這類別的子類別, 通常所有的 Animal 都會叫,
在這, "叫" 是一個函數, 如果 myObj 被宣告或定義為一個 Animal 物件,
那我們當然可以寫 myObj.叫( ); 表示 myObj 做"叫"的動作(action),
問題來了, 我設計程式之時並不知道 myObj 會是 Dog 還是 Cat, 到時可能可能是 Dog 也可能是 Cat 甚至其他類別!
一個支援多型(Polymorphism)的電腦語言會根據 myObj 是 Dog 還是 Cat 去執行正確的叫( );
如果 myObj 是 Dog, 那 myObj.叫( ); 用到的是 Dog 裡面的叫( ); 如果是 Cat 當然用到的是 Cat 裡面的叫( );
這在程式語言中的專業術語叫做動態綁定(dynamic binding; 動態繫結), 意思是在執行階段(Run time)才決定啦。
而這個動態綁定函數的專業術語就是多型(Polymorphism)啦。
不太懂? 沒關係, 因為這些議題已經超出我們課程的範圍, 該議題留給資工系的同學去傷腦筋即可 :-)
但是繼承(Inheritance) 或 擴充(extends)的概念很重要!
所以我們現在用真實世界的概念來試著讓大家理解。
類別的繼承概念可以用我們小時候就學過的"界門綱目科屬種..."來作說明,
想起來了嗎?
動物與植物都是生物!
所以動物與植物都繼承了生物的特性, 但又各自添加了不一樣的屬性(資料)與方法(動作行為)。
然後, 動物界又分為42門, 不記得? 哈哈 .. 我也不記得:-)
人類是動物界的脊索動物門, 哺乳綱, 靈長目, 人科, 人屬, 人種;
老師是人, 學生也是人, 也就是說老師與學生都是從"人"擴充(extends)來的!
(雖然有一部電影叫做 "老師不是人")
繼承(inherits)或擴充(extends)的概念非常重要, 例如已經有個類別叫做鬧鐘,
現在要設計豪華鬧鐘, 你該不會從 0 做起吧?
英文有句話很有名: Do NOT re-invent the wheel !
意思是不必再重新發明輪子, 已經有人發明了你就拿來用! (嚴格說來把輪子拿來用並不是繼承, 只是使用)
既然已經有鬧鐘, 顯然豪華鬧鐘也是鬧鐘,
所以我們只要把鬧鐘拿來"擴充"並略加修改(modify)即可:
class 豪華鬧鐘 extends 鬧鐘 {
// ... 添加或蓋掉某些原有的屬性或方法(函數)
} // class
也就是說, 只要有類似這種 YY 就是 GG 的關係(YY is a GG; 豪華鬧鐘 is a 鬧鐘),
或者該說 YY 是 GG 的一種特例, 例如 豪華鬧鐘 是 鬧鐘 的一種特例; 既然 YY is_a GG,
則 可以把 GG 拿來擴充(extends)為 YY, 那麼在 Java 語言就可以寫成:
class YY extends GG {
// 新增的屬性或欄位或說變數
// 新增的函數或說方法, 包括要把原來 GG 已有的函數蓋掉(Override)的新函數
}
這就是所謂的繼承(inherits)或是擴充(extends)的概念,
是物件導向四大概念中很重要的概念, 有了這概念, 節省了程式設計師很多的時間!
所有的物件都是物件! 這是 Flash AS3 與 Java 語言的基本理念, 萬物都是"物件", 萬物皆源自"物件";
所以,在Flash 的 Action Script 3.0中,開天闢地第一個物件類別與 Java 語言相同, 都是一個叫做 Object 的類別,
因為所有的其他物件皆源自於它,也就是所有的物件類別都是從 Object 繼承下來的子子孫孫。
在該些子子孫孫當中, 有一個類別是可以顯示在畫面上的, 稱為可視物件(DisplayObject)或翻譯為可顯示物件,
急著想知道DisplayObject可顯示物件的可以點這跳到後面看(看完可以點視窗左上角的回到這)。
最常用的影片片段(MovieClip)即是 flash.display.DisplayObject 類別(簡稱 DisplayObject)的子類別(subclass);
也就是說, flash.display.MovieClip 類別是從 flash.display.DisplayObject 類別擴充(extends)而來的;
反過來說, DisplayObject 是 MovieClip 的父類別(super class); 當然你要翻譯為母類別也是可以啦:-)
不要把 super class 翻譯為超級類別喔! 那樣很多人可能搞不清黑市蝦密碗糕, 還以為是超人的爸爸ㄟ。
所以, 在 Flash 與 Java 我們可以說任何物件都是 Object (物件國語就是俗稱的"東西", 物件是台語, 發音如"麵件")
Object → … → DisplayObject → MovieClip
Object → … → DisplayObject → Sprite
在 Flash 的 AS3 程式中, 可以任意創建物件, 不必事先定義類別(class), 例如:
var aa={age:25, height:175};
這是將 aa 宣告成物件型態,
此物件將帶著age、height的參數屬性(Property; attribute),Flash 物件的特性可以持續增加新的屬性(Java不可以喔!)。
使用物件也很簡單, 例如以下句子(statement)應該一看就知其意義:
var ww: Number = aa.height;
aa.age += 1; // 加 1 到 aa.age 使其增加一歲 :-)
還有, Flash 可以任意添加新的屬性:
aa.weight=75;
aa.email= "somebody@gmail.com";
這樣就自動多出了兩種屬性(property, attribute; 或稱之為 member data 成員資料)。
以上我們首先創建一個 aa 物件,然後就可以不斷的擴充添加新的屬性,並且填入不同的值。
這種寫法,原則上就是直接引用始祖物件 Object 類別的寫法。
Flash 也可以事先定義嚴謹型的類別,必須寫在外部 .as 檔案,嚴謹型類別事先規劃該類物件的屬性與方法,
之後使用者就只能讀取、設定到該些屬性,而無法再有其他的屬性值。
當然你還是可以 extends 擴充該類別為新的類別,以便添加其他屬性與方法(method, 即函數 function)。
以下是物件導向的類別 NameCard 的範例,必須寫在獨立的 .as 檔案。
package {
// package資料包,或稱套件; 為獨立命名空間
public class NameCard extends Object {
//宣告一個公用(public)別,稱之為 NameCard,繼承(Extends)開天闢地第一個 類別 Object
public function NameCard( ) { // 建構子 Constructor
//物件被創建( new ) 出來後立刻會做的事情要寫在這
super( ); //告訴繼承的類別(Object)訊息; 若括號內是空的可以不必寫!
}
//////
public age: int;
//具備年齡的屬性
public height:Number;
//具備身高的屬性
public wet:Number; // weight 體重, 偷懶用 wet
//具備體重的屬性
} // class
} // package
再提醒:
類別(class)不能夠直接寫在影格上,必須寫在外部的. as 文件檔案中,與 Flash 的 .fla 檔案放同一個目錄。
更多關於 ActionScript 的變數舉例說明可以點這連過去看(英文)(開新窗)
Top
如何從程式碼中創建一個物件 ?
當我們已經寫好了一個類別之後,總是要把它放入我們的程式中。其寫法很簡單,
就像新增一般的物件一樣,例如:
var bb: NameCard = new NameCard( ); // 注意這物件佔據記憶體, 但我們看不見