官术网_书友最值得收藏!

第6章 面向對象編程基礎

面向對象的編程(Object-Oriented Programming,OOP)以對象為基本單元來進行代碼劃分,組織程序代碼。ActionScript 3.0是一個完全標準的面向對象編程語言。面向對象編程在Flash 5已經開始支持,但語法不是業界傳統的編程語言格式,因此在Flash 5和Flash MX中編寫面向對象的編程非常不方便。ActionScript 2.0在面向對象的編程上有很大的進步,但是由于它的使用并不完全符合標準,存在很多的問題。ActionScript 3.0的推出基本解決了ActionScript 2.0中存在的問題,并有了很多的改進,而且相對于其他的OOP語言,ActionScript 3.0更簡單易學。

6.1 面向對象編程技術概述

面向對象編程中最重要也最難以理解的概念就是“對象”。對象,指的是具有某種特定功能的程序代碼。

對象(Object)具體可以指一件事、一個實體、一個名詞,一個具有自己特定標識的東西。比如汽車、人、房子、桌子、植物、支票、雨衣等都是對象。對象就是一種客觀存在,可能有時你覺得虛無縹緲,但是卻的的確確存在著。

任何一個對象都有其屬性。以人為例,人有身高、體重、性別、血型、年齡等,這些都反映了人作為一個社會存在所共有的特性。把這些特性反映到編程語言中,這些特性就是屬性,用來反映某一個對象的共有特點。

任何一個對象都有其方法。還是以人為例,人要吃飯、睡覺、走路、工作等,這同樣反映了人作為一個社會群體都要做的事情,是人的共有方法。存在這些共有方法,人才是一個活生生的人。人活在世上,都要做而且能做一些事情。把這些能做的事情反映到程序語言中,這些事情就是對象的方法。對象正是利用這些方法去做它能夠做的事情。

屬性和方法構成了對象,或者說屬性和方法是對象的本質組成部分。有了對象和方法,對象才能稱為一個真正的對象。

面向對象編程的基本表現就是把對象的屬性和方法包裝成類。類是面向對象編程的核心內容。

在ActionScript 3.0中,Adobe公司已經設計好很多用于實現不同功能的類,這些是ActionScript編程語言的基礎,習慣上稱為核心類。常用的ActionScript 3.0核心類包括:用于處理顯示對象的Display(顯示對象)類;用于處理數組的Array(數組)類;用于處理數字和數學的Math類,用于處理繪制效果的Shape(繪制)類等。這些內容將在第三篇“ActionScript 3.0核心類”中詳細地講解。

除了Adobe公司所提供的這些核心類之外,可以使用這些核心類所提供的方法,開發屬于自己的類。面向對象編程的主要工作就是利用自定義的類實現新的工作和方法,為自己的項目開發服務。

下面還是以人為例,給出一個簡單類(Class)的例子。

    //定義包
    package {
        //創建類
    public class Person {
                //定義屬性
        public var personname:String;
              private var age:int;
              public var birth:int;
              //構造函數
        public function Person(username:String,ages:int) {
              //利用構造函數,初始化屬性變量
              personname=username;
              age=ages;
              }
              //定義一個方法
              public function getbirth() {
                    //獲取當前時間
                    var date:Date=new Date;
                    獲取當前的年份并減去年紀
                    birth=date.getFullYear() - age;
                    //返回出生年份
                    return birth;
              }
        }
    }

在類中給人(Person)設置了3個屬性personname(人的姓名)、age(年齡)、birth(出生年份),設置了一個方法getbirth(取得出生年份)。

把該段代碼保存在Person.as文件中,然后新建一個Person.fla文件,和Person.as保存在同一個目錄下。下面建立一個人的實例(建立實例的方法,請參見6.2.3小節的內容),并通過getbirth()方法來取得此人的出生年份。代碼如下所示:

    //建立人的實例
    var p:Person=new Person"張小姐",20;
    //通過getbirth()方法取得出生年份
    trace(p.getbirth());//輸出:1988

6.2 類

對象是抽象的概念,要想把抽象的對象變為具體可用的實例,必須使用類。使用類來存儲對象可保存的數據類型及對象可表現的行為信息。要在應用程序開發中使用對象,就必須要準備好一個類,這個過程就好像制作好一個元件并把它放在庫中一樣,隨時可以拿出來使用。本節從類的基本概念著手,逐步介紹類的定義方法和類的使用方法。

6.2.1 類概述

類就是一群對象所共有的特性和行為。

早在ActionScript 1.0中,程序員使用原型(Prototype)擴展的方法,來創建繼承或者將自定義的屬性和方法添加到對象中,這是類在Flash中的初步應用。在ActionScript 2.0中,通過使用class和extends等關鍵字,正式添加了對類的支持。ActionScript 3.0不但繼續支持ActionScript 2.0中引入的關鍵字,而且還添加了一些新功能,如通過protected和internal屬性增強了訪問控制,通過final和override關鍵字增強了對繼承的控制。

下面來簡單了解一下ActionScript 3.0中類的構成。具體的類結構及實現方法,請參見6.2.2小節的內容。

?包塊和類的名稱。

?構造函數。

?屬性:包括實例屬性和靜態屬性。

?方法:包括實例方法和靜態方法。

6.2.2 創建自定義的類

創建一個自定義類的操作步驟如下:

1)建立一個準備保存類文件的目錄,即為一個包(package)。比如在計算機中有個目錄“F:\Test”。

2)啟動Adobe Flash CS3,新建一個ActionScript文件,文件名為要創建的類的名字。比如要創建的類的名稱為Sample,那么保存的文件名稱也要為Sample。注意一定要保存在剛才建立的目錄中。

3)在文件的開頭寫入package關鍵字和package包的路徑。如package Test{},其中Test就是保存類文件的目錄名稱。

4)若需要引入其他的類,則需要在package后面的大括號后插入新行,使用import語句加入其他類的包路徑和名稱。比如import flash.geom.point。若不需要,則此步驟可以省略。

5)在新的一行寫入class關鍵字和類的名字,如class Sample{}。

6)在class后面的大括號內寫入對類定義的內容,包括構造函數、屬性和方法。

注意 如果package關鍵字后面沒有聲明包路徑,即默認包路徑為當前的項目目錄。

下面用代碼的形式來顯示創建出來的類的結構和一般格式:

    package 包路徑{
        import *.*.*//引入要使用的類
        class 類名稱{
        //屬性
              private var 屬性名稱:數據類型
              public var ...
              //構造函數
              public function 類名稱{
              }
              //隱式獲取/設置方法
              public function get 屬性():返回類型{
                    return 屬性
              }
              //公共方法
              public function 方法名稱(){
              }
              //私有方法
              private function 方法名稱(){
              }
        }
    }

下面仍以人為例,建立一個完整的Person類,代碼如下所示:

    //創建包
    package {
        //創建類
        public class Person {
              //定義屬性
              public var personname:String;
              private var age:int;
              public var birth:int;
              //構造函數
              public function Person(username:String,ages:int) {
                    //在構造函數中初始化變量
                    personname=username;
                    age=ages;
              }
              //隱式獲取
              public function getpersonname():String {
                    return personname;
              }
              //隱式設置
              public function setpersonname(username:String) {
                    personname=username;
              }
                //創建做事情的方法
              public function dosomething() {
                    trace("做點什么事情呢?");
              }
              //創建獲得出生年份的方法
              private function getbirth() {
                    var date:Date=new Date;
                    birth=date.getFullYear() - age;
                    return birth;
              }
        }
    }

說明

完整的類由多個部分組成,在具體的使用過程中,需要根據具體的需要來設計。

6.2.3 創建類的實例

類是為了使用而創建的,要使用創建好的類,必須通過類的實例來訪問。要創建類的實例,需要執行下面的步驟。

1)使用import關鍵字導入所需的類文件。其用法格式如下所示:

    import 類路徑.類名稱;

格式說明如下:

?import:載入類關鍵字,必需。用于指明將導入接下來的類。

?類路徑:類包的路徑,也就是定義類中package關鍵字后的路徑。

?類名稱:要導入的類的名稱。

具體示例代碼如下所示:

    import flash.display.Sprite;

2)使用new關鍵字加上類的構造函數。其用法格式如下:

    var 類引用名稱:類名稱=new 類名稱構造函數();

格式說明如下:

?var:變量定義關鍵字,必需。

?類引用名稱:用作引用類的實例的命名,必需參數。

?類名稱:說明引用變量的類型,可選參數。推薦選擇,有助于編譯時檢測。

?new:關鍵字,必需。用于指明將創建一個該類的新實例。

?類構造函數名稱:指明要導入的類的名稱,可根據類的定義加入所需參數。

具體示例代碼如下所示。

    var sp:Sprite=new Sprite();

6.2.4 包塊和類

在ActionScript 3.0中,包路徑是一個獨立的模塊,單獨用一個包塊來包含類,不再作為類定義的一部分。定義包塊使用package關鍵字,其用法格式如下所示:

    package 包塊路徑{
    //類體
    }

用法示例代碼如下:

    package com.lzxt.display{
    //類體
    }

包塊路徑為該類存儲位置的路徑,定義之后,該類一定要存儲在該路徑的目錄下,否則編譯器就會報錯。

ActionScript 3.0中所有的類都需要定義到一個包塊內。若不需要存儲在包路徑下,只需使用package關鍵字,而不用添加包塊路徑,此時為默認的項目目錄路徑。例如下面的示例代碼也是正確的:

    package {
    //類體
    }

在ActionScript 3.0中,類和包路徑分離,類位于包塊之內。其定義格式如下所示:

    public class 類名稱 {
    //類體
    }

格式說明如下:

?public:類命名控制,用于指明類的可使用范圍。

?class:定義類關鍵字,指明將要定義一個新類。注意class的首字母是小寫而不是大寫。

?類名稱:要定義的類的名稱,使用大寫字母開頭。

具體示例代碼如下:

    public class Rect {
    //類體
    }

6.2.5 包的導入

在ActionScript 3.0中,要使用某一個類文件,就需要先導入這個類文件所在的包,也就是要先指明要使用的類所在的位置。

通常情況下,包的導入有以下3種情形:

1)明確知道要導入哪個包,直接導入單個的包。

例如說要創建一個繪制對象,那么只需導入Display包中的Shape包即可。代碼如下所示:

    import flash.display.Shape;

2)不知道具體要導入的類,使用通配符導入整個包。

例如需要一個文本的控制類,但是并不知道該類的具體名稱,就可以使用“*”通配符進行匹配,一次導入包內的所有類。具體使用代碼如下所示:

    import flash.text.*

3)要使用同一包內的類文件,則無須導入。

如果現在有多個類位于計算機中的同一個目錄下,則這些類在互相使用的時候,不需要導入,直接使用即可。

比如說現在com.lzxt.display包內有一個DrawCircle類,若同時該包還有一個類DrawSample,則在DrawSample類中使用DrawCircle時,無須導入,直接使用即可。

在com.lzxt.display包內新建一個DrawSample類文件,此類文件使用DrawCircle類構造了一個繪制圓形實例,則使用的DrawCircle類就不必事先導入。DrawSample類的代碼如下所示:

    package com.lzxt.display{
        import flash.display.Sprite;
        public class DrawSample extends Sprite {
              public function DrawSample() {
                    //生成CircleSprite對象
                    var red:DrawCircle=new DrawCircle(40,0xff0000);
                    red.x=100;
                    red.y=100;
                    //把這個對象加入顯示列表
                    addChild(red);
              }
        }
    }

要使用的DrawCircle類文件在同一包內,代碼如下所示:

    package com.lzxt.display{
        import flash.display.Sprite;
        import flash.text.TextField;
        public class DrawCircle extends Sprite {
              //聲明屬性
              private var _color:uint;
              private var _radius:Number;
              //構造函數
              public function DrawCircle(radius:Number=50,color:uint=0x00ff00) {
                    //初始化屬性
                    _radius=radius;
                    _color=color;
                    drawcircle();
              }
              //私有方法,用于繪制顯示對象
              private function drawcircle():void {
                    //下面的三行用于繪制一個圓形
                    graphics.beginFill(_color);
                    graphics.drawCircle(0,0,_radius);
                    graphics.endFill();
              }
        }
    }

說明

同一包內的類就是指位于同一個文件目錄下的類,這些類可以互相調用而不用導入。

6.2.6 構造函數

構造函數是一個特殊的函數,其創建目的是為了在創建對象的同時初始化對象,即為對象中的變量賦初始值。

在ActionScript 3.0編程中,創建的類可以定義構造函數,也可以不定義構造函數。如果沒有在類中定義構造函數,那么編譯時編譯器會自動生成一個默認的構造函數,這個默認的構造函數為空。構造函數可以有參數,通過參數傳遞實現初始化對象操作。

下面的示例列出兩種常用的構造函數代碼:

    //空構造函數
    public function Sample(){
    }
    //有參數的構造函數
    public function Sample(x:String){
    //初始化對象屬性
    }

構造函數與其他的函數不同,在定義時也有一定的差別。具體差別如下:

?構造函數必須和類名完全相同,首字母必須大寫。

?構造函數只能使用public訪問控制,不能使用其他命名空間。

?不能在構造函數中使用return語句返回值,但可以使用return語句控制程序的流程。

?構造函數不能聲明返回類型。

下面的示例構建一個完整類的構造函數,代碼如下所示:

    package com.lzxt.classes{
        public class Sample {
              //定義一個變量_str
        private var _str:String;
              //構造函數
        public function Sample(str:String) {
              //輸出
              trace("這是一個構造函數");
              //初始化變量_str
              _str=str;
              trace(_str);
              }
        }
    }

下面使用該構造函數創建一個對象,并利用其構造函數向對象傳遞一個參數。示例代碼如下所示:

    //導入類
    import com.lzxt.classes.Sample;
    //創建一個Sample對象
    var sp:Sample=new Sample("進入了AS 3.0世界");

程序運行的結果如下所示:

    這是一個構造函數
    進入了AS 3.0世界

6.2.7 聲明和訪問類的屬性

在編程語言中,使用屬性來指明對象的特征和對象所包含的數據信息以及信息的數據類型。在定義類的過程中,需要通過屬性來實現對象特征的描述和對象信息數據類型的說明。比如在創建一個關于人的類的過程中,就需要說明人這一對象的“性別”特征,需要說明人的“年齡”這一數據的數據類型是一個數字等。本小節將介紹聲明和訪問類屬性的方法。

在ActionScript 3.0的類體中,一般在class語句之后聲明屬性。類的屬性分兩種情況:實例屬性和靜態屬性。實例屬性必須通過創建該類的實例才能訪問,而靜態屬性則不需要創建類實例就能夠訪問。

聲明實例屬性的語法格式如下所示:

    var 屬性名稱:屬性類型;
    var 屬性名稱:屬性類型=;
    public var 屬性名稱:屬性類型=;

用法示例代碼如下:

    var _x:Number;
    var name:String="lzxt";
    public var birthday:Date;
    public var age:Number=30;

聲明實例屬性需要注意下面幾點:

?聲明實例屬性可以直接給屬性賦值,但不能把表達式賦值給屬性。

?var關鍵字之前可以添加訪問控制標識。若沒有使用訪問控制,默認為internal。其他的標識還有:public、private、protect。

?實例實現只有在包內可以訪問,包外不能訪問。

ActionScript 3.0中,訪問控制符有4個,其主要控制范圍如下:

?internal(默認):對同一包中的引用可見。

?private:對同一類中的引用可見。

?protected:對同一類及派生類中的引用可見。

?public:對所有位置的引用可見。

要訪問實例屬性,需先創建該類的實例,然后使用“.”運算符來訪問。

下面的示例先創建一個類,然后創建該類的實例并訪問類的屬性。代碼如下所示:

    package com.lzxt.classes{
        //創建類
        public class ClassSample {
              //創建一公共屬性,并設置其默認值
              public var username:String="浪子嘯天";
              //定義一公共屬性,設置其數據類型為數值型
              public var age:int;
              //構造函數,并通過構造函數傳遞參數
              public function ClassSampleages:int {
                    age=ages;
              }
        }
    }

下面先創建一個ClassSample對象的實例,并訪問其屬性。示例代碼如下所示:

    //導入類
    import com.lzxt.classes.ClassSample;
    //創建ClassSample類的一實例
    var mysample:ClassSample=new ClassSample(30);
    //輸出ClassSample對象實例的usernameage屬性,獲取相關信息
    trace(mysample.username);
    trace(mysample.age);

程序運行的結果如下所示:

    浪子嘯天
    30

使用實例屬性,需要先創建類的實例,然后才能訪問其屬性。靜態屬性則不同,它不用創建類的實例就可以訪問。

靜態屬性的定義格式如下所示:

    static var 屬性名稱:屬性類型;
    static var 屬性名稱:屬性類型=;
    public static var 屬性名稱:屬性類型;
    public static var 屬性名稱:屬性類型=;

要聲明一個常量,則需要使用const關鍵字,而且需要在聲明時就賦值。其具體格式如下:

    static const 屬性名稱:屬性類型=;

可以直接使用靜態屬性名稱來訪問靜態屬性。若要在外部訪問類的屬性,可使用類名加“.”運算符來實現。

下面的示例先創建一個類,然后從外部進行訪問。代碼如下所示:

    package com.lzxt.classes{
        //創建類
        public class StaticClass {
              //創建靜態屬性
              public static   var username:String="浪子嘯天";
              public static   var age:int=30;
              //創建構造函數并傳遞參數
              public function StaticClass(ages:int) {
                    age=ages;
              }
        }
    }

下面的代碼可以實現訪問靜態屬性,示例代碼如下所示:

    //導入類
    import com.lzxt.classes.StaticClass;
    //通過訪問靜態屬性訪問屬性,獲取信息
    trace(StaticClass.username);
    trace(StaticClass.age);

程序運行的結果如下所示:

    浪子嘯天
    30

6.2.8 聲明和訪問類的方法

在編程語言中,使用方法來構建對象的行為,即對象可以完成的操作。在編程過程中,通過對象的方法,告訴對象可以做什么事情,怎么做。比如在創建一個關于人的類的過程中,就需要知道人能夠干什么事情,這就是人這一對象的方法。比如人張口說話、舉手等行為,都需要通過方法來表示。

在ActionScript 3.0中,聲明類實例方法的格式和上面函數的格式類似,格式如下所示:

    function 方法名稱(參數...):返回類型{
    //方法內容
    }

和訪問類屬性一樣,訪問類實例方法,也可以使用實例名稱加“.”運算符來實現。

下面的示例先創建一個類,然后創建該類的實例并訪問類的方法。代碼如下所示:

    package com.lzxt.classes{
        //創建類
        public class ClassMeth {
              //構造函數
              public function ClassMeth() {
              }
              //創建該類的方法,在訪問此方法時,將執行一個輸出操作
              public function SampleMeth() {
                    trace("這是一個實例方法");
              }
        }
    }

訪問代碼如下所示:

    import com.lzxt.classes.ClassMeth;
    //創建ClassMeth對象的一個實例
    var me:ClassMeth=new ClassMeth();
    訪問其SampleMeth()方法
    me.SampleMeth();//輸出:這是一個實例方法

和靜態屬性一樣,也可以創建靜態方法,用于在不創建類實例的前提下訪問類方法。Meth類中定義的方法,基本都是靜態方法,均可以通過類直接訪問。

聲明靜態方法的格式如下所示:

    static function(參數...):返回類型{
    //方法內容代碼
    }
    public static function(參數...):返回類型{
    //方法內容代碼
    }

要訪問靜態方法,同樣可以使用類名稱加“.”運算符來訪問。

下面的示例創建一個類,并從外部訪問其靜態方法。代碼如下所示:

    package com.lzxt.classes{
        public class StaticMeth {
              public function StaticMeth() {
              }
              //使用static關鍵字定義一個靜態方法
              public static function SampleMeth() {
                    trace"這是一個靜態方法";
              }
        }
    }

訪問代碼如下所示:

    import com.lzxt.classes.StaticMeth;
    //不用創建實例,直接訪問該方法
    StaticMeth.SampleMeth();//輸出:這是一個靜態方法

此外,在ActionScript 3.0中仍然支持使用get和set方法隱式地獲取和設置類的屬性。其用法格式分別如下:

    //獲取屬性
    訪問控制符 function get 方法名(參數:參數類型):返回類型{
    //控制代碼
    return 訪問屬性
    }
    //設置屬性
    訪問控制符 function set 方法名(參數:參數類型):void{
    //控制代碼
    訪問屬性=參數
    }

設置后的隱式獲取和設置,可以使用實例名稱加“.”運算符來訪問。

下面的示例創建一個簡單的類Person,然后使用get和set方法訪問與設置其屬性。代碼如下所示:

    package com.lzxt.classes{
        public class Person {
              //定義私有屬性
              private var _name:String="浪子嘯天";
              //隱式獲取屬性
              public function get name():String {
                    return _name;
              }
              //隱式設置屬性
              public function set name(username:String):void {
                    _name=username;
              }
        }
    }

訪問代碼如下所示:

    import com.lzxt.classes.Person;
    //創建對象實例
    var ps:Person=new Person();
    //實現隱式獲取ps實例的屬性
    trace(ps.name);
    //實現隱式設置ps實例的屬性
    ps.name="lzxt";
    //輸出
    trace(ps.name);

程序運行的結果如下所示:

                                              浪子嘯天
                                              lzxt

6.2.9 類的使用

在ActionScript 3.0中,創建好的類一般有3種使用方法:作為文檔類進行文檔類綁定;作為庫中元件的類進行綁定;作為外部類使用import關鍵字導入。下面結合實例具體介紹這3種用法。

1. 文檔類

文檔類是ActionScript 3.0的新特色,該特色是為實現代碼與文檔分離而設計的。文檔類是繼承自Sprite或者MovieClip類的子類(繼承的方法及要求,請參見6.4節的內容),它將作為SWF文件的主類而存在。在執行SWF文件時,此文件的構造函數將被首先調用,因此該類將成為該SWF中程序的入口,任何需要做的事情都可以寫在上面。

文檔類和普通類的區別在于,文檔類必須是繼承自Sprite類或者MovieClip類的子類。

通過使用文檔類,把原來需要加在時間軸關鍵幀上的代碼放在外部的文檔中,在文檔屬性中進行綁定,實現文檔與代碼分離。

下面的實例使用文檔類在舞臺上添加一個顯示圓形對象,具體操作步驟如下:

1)打開腳本窗口,新建一個DocSample類。其代碼如下所示:

    //定義包路徑
    package com.lzxt.classes{
        //導入包
        import flash.display.Shape;
        import flash.display.Sprite;
        //定義類
        public class DocSample extends Sprite {
              //定義屬性
              public var sp:Shape;
              //構造函數
              public function DocSample() {
                    //創建對象
                    sp=new Shape();
                    sp.graphics.beginFill(0xff0000);
                    sp.graphics.drawCircle(0,0,150);
                    sp.graphics.endFill();
                    sp.x=225;
                    sp.y=200;
                    //加入場景
                    addChild(sp);
              }
        }
    }

2)新建一個Flash文件(ActionScript 3.0),保存文件到com同級的目錄下。

3)打開“屬性”面板,在“文檔類”文本框中輸入類路徑:com.lzxt.classes.DocSample,實現文檔類綁定。注意只要輸入類名稱即可,不要加.as。完成后如圖6.1所示。

圖6.1 文檔類綁定

至此,文檔類綁定完成。按下【Ctrl+Enter】組合鍵,編譯文件。完成后的效果如圖6.2所示。

圖6.2 文檔類示例效果

注意 在ActionScript 3.0面向對象編程的要求下,本書后面的示例盡可能使用文檔類使文檔和代碼分離。所提及的文檔類的使用方法與此相同,以后不再重復。

2. 與庫文件綁定

與fla文件庫中的影片剪輯進行綁定,每個影片剪輯只能綁定一個類。

下面的實例通過使用庫文件綁定,實現一個上升水泡的效果。具體操作過程如下:

1)新建一個Flash文件(ActionScript 3.0),保存文件為addMovieClip。

2)單擊【插入】|【新建元件】命令,打開“創建新元件”窗口,在“名稱”文本框中輸入影片剪輯的名稱“水泡”,單擊【確定】按鈕,創建一個新的影片剪輯。

3)使用創作工具創作一個水泡的形狀效果。如圖6.3所示。

圖6.3 水泡效果圖

4)單擊【文件】|【新建】命令,打開“新建文檔”窗口,選擇“ActionScript文件”選項,單擊【確定】按鈕,新建一個腳本文件,保存為H2O,路徑和addMovieClip相同。

5)在腳本窗口輸入如下代碼:

    //
    package {
        //導入包
        import flash.display.MovieClip;
        import flash.events.*;
        //定義類
        public class H2O extends MovieClip {
              //初始化速度
              var speedx:Number=0;
              var speedy:Number=0;
              //構造函數
              public function H2O() {
                    speedx=.5 * Math.random() - 0.5;
                    speedy=5 * Math.random();
                    //注冊事件偵聽
                    this.addEventListener(Event.ENTER_FRAME,Mot);
              }
              //定義事件函數
              function Mot(e:Event) {
                    //控制位置變化
                    this.x+= speedx;
                    this.y-= speedy;
                    //運動出舞臺之后初始化
                    if (this.y < 0) {
                        init();
                    }
              }
              //初始化位置
              function init() {
                    this.y=400;
                    this.x=Math.random() * 550;
              }
        }
    }

6)回到addMovieClip.fla文件,打開“庫”面板,右擊“水泡”影片剪輯,選擇“鏈接”選項,打開“鏈接屬性”對話框。如圖6.4所示。

圖6.4 鏈接屬性

7)在“類”文本框中輸入H2O,基類保持不變。單擊【確定】按鈕。

8)打開“動作”面板,輸入如下代碼:

    //自定義顯示函數
    function DisplayH2O() {
          //使用循環載入多個顯示對象
          for(var i:int = 0; i <100; i++){
                //載入對象
                var h2o:H2O = new H2O();
                //加入舞臺
                this.addChild(h2o);
                //控制初始位置和屬性
                h2o.x = Math.random()*550;
                h2o.y = Math.random()*300+400;
                h2o.alpha = .2+Math.random()*.5;
                var scale:Number = .3+Math.random();
                h2o.scaleX = h2o.scaleY = scale;
          }
    }
    //執行函數
    DisplayH2O();

至此,此動畫效果制作完成,完成后的效果如圖6.5所示。

圖6.5 綁定庫元件動畫效果圖

3. import導入類

此方法在前面的創建類實例一節已經介紹了實例,此處不再贅述。

6.2.10 包外類

在ActionScript 3.0中,一個類文件中可以定義多個類,但是包塊內只能定義一個類,此為主類。主類的名稱一定要和類文件的名稱相同,這個類是供外部使用的。在包塊之外,還可以定義多個類,這些類的名稱和類文件的名稱不同,而且只有當前類中的成員可以訪問。這種類,有些資料稱其為包外類,有些資料稱其為助手類。在這里使用包外類這一名稱。

包外類的格式如下所示:

    package 包路徑{
          class 主類{
    //主類內容
    }
    }
    class 包外類1{
    //包外類內容
    }
    class 包外類2{
    //包外類內容
    }

下面的示例使用包外類,具體代碼如下所示:

    //創建包
    package com.lzxt.display{
        import flash.display.Sprite;
        //創建主類
        public class Draw extends Sprite {
              //構造函數
              public function Draw() {
                    //使用包外類,通過創建該類的實例來創建對象
                    var red:DrawCircle=new DrawCircle(40,0xff0000);
                    red.x=100;
                    red.y=100;
                    addChild(red);
              }
        }
    }
    //包外類
    import flash.display.Sprite;
    import flash.text.TextField;
    //創建一個繪制圓形的類
    class DrawCircle extends Sprite {
        private var _color:uint;
        private var _radius:Number;
        public function DrawCircle(radius:Number=50,color:uint=0x00ff00) {
              _radius=radius;
              _color=color;
              drawcircle();
        }
        private function drawcircle():void {
              graphics.beginFill(_color);
              graphics.drawCircle(0,0,_radius);
              graphics.endFill();
        }
    }

包外類在使用的過程中,需要注意以下幾點:

?包外類只對當前類文件可見,故不能使用public關鍵字定義。

?包外類需要重新導入要使用的包,包塊內導入的無效。

?包外類的名字如果和包內的類重復,優先使用包外類。

6.3 接口

接口可以看做是對象之間相互聯系的紐帶,起橋梁的作用。通過接口中方法聲明的集合,能夠使互不相干的對象之間相互通信。

接口和類既存在一些類似的地方,也有一定的區別。

?接口僅僅聲明方法而不提供實現的方法,要實現方法,需要在該接口的類中聲明和實現。

?接口方法的實現無任何屬性,但在接口類的定義中,實現的方法必須為public。

?可通過extends語句由接口繼承實現多個接口,也可以通過implements語句由類繼承實現。

?接口是一個定義類方法組的數據類型,可作為類型注釋。

6.3.1 接口的定義

定義接口的方法和定義類相似,不過需要使用interface關鍵字來實現。

接口可以包含實例方法、靜態方法、get和set方法。

接口也需要保存為as文件,文件名必須和接口名完全相同。

定義接口的語法格式如下所示:

    package 包路徑{
      訪問控制 接口名稱{
                function 實例方法名(參數:參數類型):返回類型;
                static function 靜態方法名(參數:參數類型):返回類型;
                function get 方法名():返回類型;
                function set 方法名(參數:參數類型):void;
      }
    }

接口定義示例代碼如下所示:

    //
    package {
        //定義接口IPerson
        public interface IPerson {
              //定義方法
              function say():void;
              function walk():void;
        }
    }

接口定義中需要注意以下幾點:

?接口的定義需要使用interface關鍵字。

?接口方法的定義不能包含訪問控制關鍵字。

?接口中只能定義方法,不能定義屬性。

?接口的名稱通常用大寫字母I開頭。

6.3.2 在類中實現接口

接口只是負責定義一些方法,這些方法要實現,則必須使用接口類來完成。接口類要使用implements關鍵字來實現。一個類可以實現多個接口,多個接口之間使用“,”分開。同樣一個接口可以由多個子類來繼承。

下面的示例代碼繼承6.3.1小節中的IPerson接口,并創建子類Man。代碼如下所示:

    package {
        //定義類Man,繼承自接口IPerson
        public class Man implements IPerson {
              //定義類方法walk
              public function walk():void {
                    trace("男人走路有力量?。?/span>");
              }
              //定義類方法say
              public function say():void {
                    trace("男人說話直截了當!");
              }
        }
    }

使用接口創建類的使用示例代碼如下所示:

    package {
        import flash.display.Sprite;
        public class DoMan extends Sprite {
              public function DoMan() {
                    //創建Man類的實例
                    var man:Man=new Man;
                    man.walk();
                    man.say();
                    /*
                    男人走路有力量??!
                    男人說話直截了當!
                    */
              }
        }
    }

繼承接口實現子類的方法時要注意以下幾方面:

?從接口中繼承的方法必須使用public關鍵字控制。

?從接口中繼承方法的參數的數量、數據類型及訪問類型也必須相同。

?參數的名稱和參數的默認值可以與接口中不同。

6.4 繼承

繼承(Inheritance)是面向對象技術的一個重要概念,也是面向對象技術的一個顯著特點。一個對象通過繼承可以使用另一個對象的屬性和方法。準確來說,繼承的類具有被繼承類的屬性和方法。被繼承的類,稱為基類或者超類,也可以稱為父類;繼承出來的類,稱為擴展類或者子類。

6.4.1 繼承的定義

類的繼承要使用extends關鍵字來實現。其語法格式如下所示:

    package{
      class 子類名稱 extends 父類名稱{
      }
    }

下面的示例創建一個新類Man,它繼承自Person類,這樣Man類就是子類,而Person類就是父類。用法示例代碼如下:

    package{
        class Man extends Person{
        }
    }

6.4.2 屬性和方法的繼承

子類可以繼承父類中的大部分的屬性和方法,但是父類中使用“private”訪問控制符定義的屬性和方法不能被繼承。

下面的示例新建一個PC類作為父類,該類有兩個實例屬性name和age,有兩個實例方法walk()和say()。

創建父類PC,代碼如下所示:

    package com.lzxt{
        //構建類
        public class PC {
              //構建屬性
              public var name:String="浪子嘯天";
              public var age:int=30;
              //構建方法
              public function walk():void {
                    trace("人可以走路!");
              }
              public function say():void {
                    trace("歡迎你來到as3世界");
              }
        }
    }

創建子類Man,代碼如下所示:

    package com.lzxt{
        //繼承父類
        public class Man extends PC{
        }
    }

下面使用文檔類創建子類Man對象的一個實例,并訪問父類PC的屬性和方法,代碼如下所示:

    package {
        import flash.display.Sprite;
        import com.lzxt.Man;
        //文檔類
        public class SampleIt extends Sprite {
              //構造函數
              public function SampleIt() {
                    //構建實例對象
                    var man:Man=new Man();
                    //獲取屬性
                    trace(man.name);
                    trace(man.age);
                    //獲取方法
                    man.say();
                    man.walk();
              }
        }
    }

程序運行后的結果如下所示:

    浪子嘯天
    30
    人可以走路!
    歡迎你來到as3世界

說明

輸出的結果表明,子類的對象繼承了父類的方法和屬性。

6.4.3 重寫(override)

通過繼承,子類可以繼承父類的屬性和方法。但有些時候只需要使用父類中的方法名稱,而需改變其內容,這時就需要利用重寫來修改其方法內容。

在ActionScript 3.0中,只能重寫實例的方法,不能重寫實例的屬性。另外,父類中方法的訪問控制符為final的方法也不能進行重寫。

下面在6.4.2小節的子類Man中重寫父類PC的方法walk(),代碼如下所示:

    package com.lzxt{
        //繼承父類
        public class Man extends PC {
              public override function walk():void {
                    trace("這是重寫過的走路方法");
              }
        }
    }

繼續使用文檔類SampleIt,編譯后的輸出結果如下:

    浪子嘯天
    30
    歡迎你來到as3世界
    這是重寫過的走路方法

說明

輸出的結果表明,已經覆蓋了父類的方法walk()。

使用override方法重寫父類的方法,需要注意下面幾點:

?一旦使用了override關鍵字,重寫方法的方法父類中一定要存在。

?不能重寫final關鍵字定義的方法。

?重寫的方法必須與父類方法的參數和返回類型聲明完全一致。它們參數的數量必須相同,而且每個參數的類型也要相同。若父類方法的參數是可選的,則重寫的函數該參數也必須是可選的。

?父類和子類這兩個函數的訪問控制符和命名空間屬性也必須相同。

6.5 AS 3.0命名空間

在ActionScript 3.0中引入了命名空間的概念。使用命名空間,可以控制標識符的可見性,可以管理各個屬性和方法的可見性。不管命名空間是在內部還是外部,都可以應用于代碼。ActionScript 3.0中有4個訪問控制符,分別為:public、private、internal和protected。這4個訪問控制符就是一種命名空間,同樣,也可以定義自己的命名空間。本節就來介紹一下自定義命名空間和應用命名空間的方法。

6.5.1 命名空間的定義

命名空間常見的情況有兩種:一是將命名空間定義到一個獨立的as文件中,該命名空間能夠使不同的包進行訪問;二是將命名空間定義在類體中,該命名空間僅在本類中進行訪問。

1. 將命名空間定義在一個獨立的as文件中

下面的示例定義一個lzxt命名空間,代碼如下所示:

    package{
        //定義命名空間
        public namespace lzxt = "http://www.flacs.cn/";
    }

說明

從示例可以看出,定義一個命名空間需要使用namespace關鍵字。

2. 將命名空間定義在類體中

定義在類體中的命名空間也使用namespace關鍵字,命名空間之前可以使用訪問控制符。下面創建一個示例,代碼如下所示:

    package {
        class SampleSpace {
              //定義命名空間
              namespace flasc
              //獲取命名空間方法
              public function getNameSpace():Namespace {
                    return flasc;
              }
              //使用自定義命名空間控制方法
              flasc function welcome():void {
                    trace("歡迎使用自定義命名空間");
              }
        }
    }

說明

在類體中定義命名空間,是一種很好的處理方式。

6.5.2 使用命名空間

若在類體中定義命名空間,則可以像訪問控制符一樣使用,在定義的屬性或者方法之前加上命名空間即可。如下面的代碼:

    package {
        class SampleSpace {
              //定義命名空間
              namespace lzxt
              lzxt var name:String="浪子嘯天";
              //使用自定義命名空間控制方法
              lzxt function welcome():void {
                    trace("歡迎使用自定義命名空間");
              }
        }
    }

若要使用獨立的命名空間,則需要使用use關鍵字,代碼如下所示:

命名空間類:

    package{
        //定義命名空間
        public namespace lzxt = "http://www.flacs.cn/";
    }

使用命名空間類:

    package{
        //打開命名空間lzxt
          use namespace lzxt;
          public class Samplelzxt{
            //用命名空間lzxt定義doSth 方法
            lzxt function sampleMeth():void{
            trace("這是一個自定義命名空間的函數");
            }
        }
    }

文檔類:

    package {
        import flash.display.MovieClip;
        //使用命名空間
        use namespace lzxt;
        public class TestNameSpace extends MovieClip {
              public function TestNameSpace() {
                    //構建實例
                    var sam:Samplelzxt=new Samplelzxt();
                    //執行方法
                    sam.sampleMeth();
                    //輸出:這是一個自定義命名空間的函數
              }
        }
    }

命名空間主要可以用于處理以下問題:

?避免命名沖突。

?更加靈活高效地實現訪問控制。

?實現不公開的API接口。

6.6 練習題

1. 關于訪問控制符,描述不正確的是( )。

A. 類可以用public private final來聲明

B. 使用final聲明的方法,不可以被繼承

C. 使用internal聲明的方法,只能被同一包訪問

D. 使用protected聲明的方法,不能被其他類訪問,只能由自己和子類訪問

2. 關于override描述正確的是( )。

A. 使用override可以重寫父類public聲明的屬性

B. 使用override可以重寫父類protected聲明的方法

C. 方法被重寫時,參數數量需一致,參數類型可以不同

D. final聲明的方法也可以被重寫

3. 簡述接口和類的區別及什么時候需要使用接口。

4. 關于AS3的接口,描述正確的是( )。

A. 一個類可以繼承多個接口

B. 接口中可以定義方法和屬性

C. 接口中定義的方法可以有public protected描述訪問權限

D. 繼承接口的類,可以不去實現接口中的方法

5. 用文檔類和庫文件綁定的方式實現以下程序。

定義一個類—人(Person),實現方法—行走run()和站立stand(),run()讓人以10px/s移動,定義男人Man繼承Person,重寫run(),以20px/s移動。在文檔類里,創建Person和Man的兩個對象添加到舞臺,并調用它們的run()。

主站蜘蛛池模板: 涟源市| 崇左市| 临泽县| 宜昌市| 赣榆县| 汕头市| 平武县| 牙克石市| 襄城县| 图片| 太康县| 剑川县| 汕头市| 湘阴县| 霍城县| 明光市| 林甸县| 梅河口市| 乐平市| 安岳县| 隆化县| 静海县| 上虞市| 义马市| 文化| 岳阳市| 克东县| 清河县| 普定县| 景德镇市| 阜康市| 桂平市| 武清区| 宁陕县| 巴青县| 探索| 郁南县| 乌兰察布市| 延吉市| 安达市| 滨海县|