標籤:style blog http color 使用 cti
附屬指令碼
附屬指令碼 可以定義在類(Class)、結構體(structure)和枚舉(enumeration)這些目標中,可以認為是訪問對象、集合或序列的捷徑,不需要再調用執行個體的特定的賦值和存取方法。舉例來說,用附屬指令碼訪問一個數組(Array)執行個體中的元素可以這樣寫someArray[index]
,訪問字典(Dictionary)執行個體中的元素可以這樣寫 someDictionary[key]
。
對於同一個目標可以定義多個附屬指令碼,通過索引實值型別的不同來進行重載,而且索引值的個數可以是多個。
譯者:這裡附屬指令碼重載在本小節中原文並沒有任何示範
附屬指令碼文法
附屬指令碼允許你通過在執行個體後面的方括弧中傳入一個或者多個的索引值來對執行個體進行訪問和賦值。文法類似於執行個體方法和計算型屬性的混合。與定義執行個體方法類似,定義附屬指令碼使用subscript
關鍵字,顯式聲明入參(一個或多個)和傳回型別。與執行個體方法不同的是附屬指令碼可以設定為讀寫或唯讀。這種方式又有點像計算型屬性的getter和setter:
subscript(index: Int) -> Int { get { // 返回與入參匹配的Int類型的值 } set(newValue) { // 執行賦值操作 }}
newValue
的類型必須和附屬指令碼定義的傳回型別相同。與計算型屬性相同的是set的入參聲明newValue
就算不寫,在set代碼塊中依然可以使用預設的newValue
這個變數來訪問新賦的值。
與唯讀計算型屬性一樣,可以直接將原本應該寫在get
代碼塊中的代碼寫在subscript
中:
subscript(index: Int) -> Int { // 返回與入參匹配的Int類型的值}
下面代碼示範了一個在TimesTable
結構體中使用唯讀附屬指令碼的用法,該結構體用來展示傳入整數的n倍。
struct TimesTable { let multiplier: Int subscript(index: Int) -> Int { return multiplier * index }}let threeTimesTable = TimesTable(multiplier: 3)println("3的6倍是\(threeTimesTable[6])")// 輸出 "3的6倍是18"
在上例中,通過TimesTable
結構體建立了一個用來表示索引值三倍的執行個體。數值3
作為結構體建構函式
入參初始化執行個體成員multiplier
。
你可以通過附屬指令碼來來得到結果,比如threeTimesTable[6]
。這句話訪問了threeTimesTable
的第六個元素,返回18
或者6
的3
倍。
注意:
TimesTable
例子是基於一個固定的數學公式。它並不適合開放寫入權限來對threeTimesTable[someIndex]
進行賦值操作,這也是為什麼附屬指令碼只定義為唯讀原因。
附屬指令碼用法
根據使用情境不同附屬指令碼也具有不同的含義。通常附屬指令碼是用來訪問集合(collection),列表(list)或序列(sequence)中元素的捷徑。你可以在你自己特定的類或結構體中自由的實現附屬指令碼來提供合適的功能。
例如,Swift 的字典(Dictionary)實現了通過附屬指令碼來對其執行個體中存放的值進行存取操作。在附屬指令碼中使用和字典索引相同類型的值,並且把一個字典實值型別的值賦值給這個附屬指令碼來為字典設值:
var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]numberOfLegs["bird"] = 2
上例定義一個名為numberOfLegs
的變數並用一個字典字面量初始化出了包含三對索引值的字典執行個體。numberOfLegs
的字典存放實值型別推斷為Dictionary<String, Int>
。字典執行個體建立完成之後通過附屬指令碼的方式將整型值2
賦值到字典執行個體的索引為bird
的位置中。
注意:
Swift 中字典的附屬指令碼實現中,在get
部分傳回值是Int?
,上例中的numberOfLegs
字典通過下邊返回的是一個Int?
或者說“可選的int”,不是每個字典的索引都能得到一個整型值,對於沒有設過值的索引的訪問返回的結果就是nil
;同樣想要從字典執行個體中刪除某個索引下的值也只需要給這個索引賦值為nil
即可。
附屬指令碼選項
附屬指令碼允許任意數量的入參索引,並且每個入參類型也沒有限制。附屬指令碼的傳回值也可以是任何類型。附屬指令碼可以使用變數參數和可變參數,但使用寫入讀出(in-out)參數或給參數設定預設值都是不允許的。
一個類或結構體可以根據自身需要提供多個附屬指令碼實現,在定義附屬指令碼時通過入參個類型進行區分,使用附屬指令碼時會自動匹配合適的附屬指令碼實現運行,這就是附屬指令碼的重載。
一個附屬指令碼入參是最常見的情況,但只要有合適的情境也可以定義多個附屬指令碼入參。如下例定義了一個Matrix
結構體,將呈現一個Double
類型的二維矩陣。Matrix
結構體的附屬指令碼需要兩個整型參數:
struct Matrix { let rows: Int, columns: Int var grid: Double[] init(rows: Int, columns: Int) { self.rows = rows self.columns = columns grid = Array(count: rows * columns, repeatedValue: 0.0) } func indexIsValidForRow(row: Int, column: Int) -> Bool { return row >= 0 && row < rows && column >= 0 && column < columns } subscript(row: Int, column: Int) -> Double { get { assert(indexIsValidForRow(row, column: column), "Index out of range") return grid[(row * columns) + column] } set { assert(indexIsValidForRow(row, column: column), "Index out of range") grid[(row * columns) + columns] = newValue } }}
Matrix
提供了一個兩個入參的構造方法,入參分別是rows
和columns
,建立了一個足夠容納rows * columns
個數的Double
類型數組。為了儲存,將數組的大小和數組每個元素初始值0.0,都傳入數組的構造方法中來建立一個正確大小的新數組。
你可以通過傳入合適的row
和column
的數量來構造一個新的Matrix
執行個體:
var matrix = Matrix(rows: 2, columns: 2)
上例中建立了一個新的兩行兩列的Matrix
執行個體。在讀取順序從左上到右下的Matrix
執行個體中的數組執行個體grid
是矩陣二維數組的扁平化儲存:
// grid = [0.0, 0.0, 0.0, 0.0] col0 col1row0 [0.0, 0.0,row1 0.0, 0.0]
將值賦給帶有row
和column
附屬指令碼的matrix
執行個體運算式可以完成賦值操作,附屬指令碼入參使用逗號分割
matrix[0, 1] = 1.5matrix[1, 0] = 3.2
上面兩條語句分別讓matrix
的右上值為 1.5,坐下值為 3.2:
[0.0, 1.5, 3.2, 0.0]
Matrix
附屬指令碼的getter
和setter
中同時調用了附屬指令碼入參的row
和column
是否有效判斷。為了方便進行斷言,Matrix
包含了一個名為indexIsValid
的成員方法,用來確認入參的row
或column
值是否會造成數組越界:
func indexIsValidForRow(row: Int, column: Int) -> Bool { return row >= 0 && row < rows && column >= 0 && column < columns}
斷言在附屬指令碼越界時觸發:
let someValue = matrix[2, 2]// 斷言將會觸發,因為 [2, 2] 已經超過了matrix的最大長度
Swift QQ群
Swift互助交流QQ群:74512850,讓愛好者共同進步!群內有完整版中文PDF文檔!
點選連結加入群【SWIFT開發互助】:http://jq.qq.com/?_wv=1027&k=NwGksV
中文手冊導航
部落格園:點擊進入導航
GitHub:點擊進入導航