使用Vector類編程
一個array(數組)就像是把一套變量組織在一起的容器。單個數組可以含有許多不同的值。你可以儲存和取得數組中的單個值(也就是數組elements(元素))。你也可以通過直接操作數組變量來成組地使用其值。最常見的是有序數組。你可以憑某個索引號從中獲取值。Action Script3包括了用於索引數組的兩個類。
- Array 類:一個可以包含各種值類型的索引數組,其包容度甚至可以允許你在同一個數組里混合各種值類型。
- Vector類:也是索引數組。其元素必須都為同一個類的實例。Vector類適用於 Flash Player 10和之后的版本。
如果你需要存儲一系列具有相同數據類型的值,與Array類相比,Vector類有一些優勢。首先,因為Vector的所有元素要求必須有相同的數據類型,所以ActionScript編譯器在代碼編譯的時候就可以進行類型檢查。任意嘗試添加或恢復錯誤類型值的代碼都將被處理為編譯時錯誤。數據類型在運行時也會進行檢查,因此,假設數據類型不能再編譯時被檢查出來,它仍然會被檢查,而且數據類型限制也還是有效的。除了類型檢查的優點之外,使用Vector類的代碼比使用Array創建的同樣代碼明顯運行得要快— —這是一個重要的優勢。
這篇快速入門描述了創建於使用Vector類的技巧。要了解更多關於Array類的使用,請參考Flash快速入門使用數組編程。
以下段落描述了使用Vector對象的常用接下來的部分描述了用Vector對象完成一般任務:創建一個Vector實例,為一個Vector對象添加值,為一個Vector對象更改值,為一個Vector對象的值分類。
基本要求
要實現這篇快速入門中的實例,你需要如下實例文件:
示例文件
這個示例存檔文件包含了如下幾個文件:
- SortVectorOfNumber.fla:一個Flash文件,演示了在Vector中對數字值進行排序,在本文中的"將一個Vector中的值進行排序"分段中進行描述。
- SortVectorOfObject.fla:一個示例演示中Vector中對常用對象進行排序,在本文中的"將一個Vector中的值進行排序"分段中進行描述。
- Person.as:Person類的源碼,在SortVectorOfObject.fla中引用。
要測試每個應用,請打開FLA文件,並選擇"控制 > 測試影片"。
預備知識
推薦有使用ActionScript3編程的一般經驗。
創建一個Vector實例
一個Vector對象是一個只保存着某類值的索引數組。Vector對象特定保存的類是Vector的基本型。而調用Vector類的構造函數的時候就創建了一個Vector對象。你也許猜到了,制定給Vector變量的基本類必須匹配調用構造函數時指定的基本型。
當創建一個Vector實例的時候,為了指定它的基本型,你要在Vector類名字上增加額外的信息, 使用一個叫做類型參數的語法格式。比如,下面的表述聲明了一個叫做myVector
的Vector變量,使用類型參數語法來指出在myVector
里的 Vector只能包含字符串類型的值。
var myVector:Vector.<String>;
當你調用Vector構造函數來實際創建Vector對象的時候可以用一樣的語法:
myVector = new Vector.<String>();
作為一種規則,只要有Vector
這個類名出現在你的代碼里,你總是要對它使用一個類型參數。
當然,你可以把變量聲明和構造實例整合到一行代碼里。
var myVector:Vector.<String> = new Vector.<String>();
盡管在這篇快速入門中所給的示例都比較簡單,例如創建String和Number作為Vector的基類型,實際上,Vector類的基類型可以是任何類。這也包括你定義的自定義類。例如,假設你的代碼定義了一個名為MyClass的類。在這種情況下,下面的代碼是有效的,它將創建一個Vector對象,它的元素都必須是MyClass實例:
var v:Vector.<MyClass> = new Vector.<MyClass>();
預設Vector的長度
Vector類構造函數有兩個可選參數,它允許你明確你的Vector實例的數量。第一個參數是length
參數。默認情況下,當一個Vector被創建時,它是空的(它有0個元素)。然而,如果你傳遞一個值給length
參數,明確元素數量的Vector實例就被創建了:
var myVector:Vector.<String> = new Vector.<String>(7); // myVector is created with 7 elements
預先確定Vector的大小比一次創建一個元素效率要高,所以,如果你提前知道Vector包含有多少元素,提供一個length
參數值是比較好的。如果Vector的基類型是一個Boolean或者一個數值類型(Number,int,uint),每個元素都會被賦予這個數據類型的默認值(Boolean的默認值false
,數據類型默認值0)。否則,每個元素初始值為null
。
創建一個可動態調整長度的Vector
Vector對象的另一個特征就是他們可以調整長度,這意味着你可以改變值,但是不能通過添加或刪除元素來改變總數。默認地,一個Vector實例是不允許動態修改長度的。要創建一個可修改長度的Vector,將Vector類構造函數的第二個參數(fixed
參數)設置為true
:
var myVector:Vector.<String> = new Vector.<String>(7, true); // myVector's length is fixed to 7 elements
注意: 你可以在任何時候修改Vector對象的fixed
屬性來設置Vector的長度是否可變。
myVector.fixed = false; // myVector's length is no longer fixed
為一個Vector對象添加值
除了一個額外的限制之外,添加一個值到Vector對象中與添加一個值到Array對象中類似。一個Vector對象的每個元素必須有一個值(或者null
)。換句話說,你不能在一個序號為4的位置添加一個值,除非Vector的0–3為已經有值了。在實際中,這意味着要添加一個新的元素到Vector中,你必須在等於Vector對象長度的序號位置添加它(因為Vector的第一個元素序號為0,所以length
屬性的值通常比Vector最后一個元素的序號要大)。下面的代碼演示了這一技巧:
var names:Vector.<String> = new Vector.<String>(); // ... assume some elements are added ... // Add an element to the end of the Vector names[names.length] = "Bob";
除了使用array訪問符([]
)操作添加一個值到Vector對象中外,你也可以使用Vector對象的push()
或者unshift()
方法來添加元素到Vector中。就像Array類一樣,push()
方法創建了一個新元素在Vector最后一個元素的末尾,unshift()
方法創建了一個新元素在Vector序號為0的位置(同時將所有已經存在的元素移位值高一位的位置):
names.push("Harold"); // adds the value "Harold" to the end of the Vector names.unshift("Fred"); // adds the value "Fred" to the start of the Vector
這些方法還有額外的優勢是,你可以傳遞多個值做為參數給方法,所有的值都會一次性添加到Vector對象中。然后,這種彈性的方式也會導致一個后果。當你使用push()
或者unshift()
方法添加值到Vector對象時,編譯器不能檢查數據類型是否匹配。因為,任何使用push()
或者unshift()
添加錯誤類型的值到Vector對象中的代碼知道運行代碼時才會被發現。
從Vector對象中恢復值
從Vector對象中恢復值與從一個Array對象中恢復值完全一樣。要從特定序號位置回復元素值,你需要使用數組訪問符([]
)操作來明確你需要的元素序號:
var name1:String = names[0];
使用數組訪問符([]
)操作恢復值,但是不會將它從Vector對象中移除。要恢復值並且將它從Vector對象中移除,請使用pop()
方法(它會移除最后的一個元素)或者shift()
方法(它會移除第0個元素,並且所有元素減一位):
var finalName:String = names.pop(); // removes the last value from the Vector var firstName:String = names.shift(); // removes the first value from the Vector
將一個Vector中的值進行排序
大部分使用Vector對象的方法與使用Array對象的方法都一樣。有一個方法你需要知道的不一樣的是在Vector對象元素排序。Vector類僅有一個方法給值排序:sort()
方法。sort()
方法不會更改原始的Vector對象。取而代之,它返回具有相同基類型包含已排序了值的一個新的Vector。
當你使用Vector類的sort()
方法時,它沒有默認的排序行為,即使是基本的數據類型如Number或者String。正因為如此,任何時候你使用sort()
方法,你都需要指明一個自定義的排序函數來定義排序邏輯。例如,下面的代碼中,一個Number類型的Vector對象使用sort()
方法來排序。在這個案例中,這個代碼演示了基本的數據排序;小的數字放在大的數字前面(升序排列)。名為sortNumbers()
的函數定義了排序行為,它做為一個參數傳遞給了sort()
方法調用。Flash Player給每個數字排序時,它調用sortNumber()
函數,將要進行比較的兩個數值傳遞給函數,結果決定最終排序的順序:
var numberVector:Vector.<Number> = new Vector.<Number>(); numberVector.push(2, 17, 3.6, 4.4, 29, -34, 0.09235); trace(numberVector); // output: 2,17,3.6,4.4,29,-34,0.09235 var sortedVector:Vector.<Number> = numberVector.sort(sortNumbers); trace(sortedVector); // output: -34,0.09235,2,3.6,4.4,17,29 function sortNumbers(x:Number, y:Number):Number { if (x < y) { return -1; } else if (x > y) { return 1; } else { return 0; } }
你可以定義為任意數據類型定義一個排序函數。例如,下面的代碼為Vector的Person對象根據姓氏(last name)進行了排序,然后是名字(first name)(它假定了有一個Person類具有firstName
和lastName
屬性):
var personVector:Vector.<Person> = new Vector.<Person>(); personVector[0] = new Person("Bob", "Smith"); personVector[1] = new Person("Harold", "Johnson"); personVector[2] = new Person("Barbara", "Smith"); personVector[3] = new Person("Arnold", "Anderson"); personVector[4] = new Person("Margaret", "Wooster"); // output:[Smith,Bob],[Johnson,Harold],[Smith,Barbara],[Anderson,Arnold],[Wooster,Margaret] trace(personVector); var sortedVector:Vector.<Person> = personVector.sort(sortPeople); // output:[Anderson,Arnold],[Johnson,Harold],[Smith,Barbara],[Smith,Bob],[Wooster,Margaret] trace(sortedVector); function sortPeople(x:Person, y:Person):Number { // sort by last name var lastNameSort:Number = sortStrings(x.lastName, y.lastName); if (lastNameSort != 0) { return lastNameSort; } else { // if the last names are identical, sort by first name return sortStrings(x.firstName, y.firstName); } } function sortStrings(x:String, y:String):Number { if (x < y) { return -1; } else if (x > y) { return 1; } else { return 0; } }