《Swift Programming Language 》——附屬指令碼(Subscripts)

來源:互聯網
上載者:User

標籤:style   java   使用   strong   io   for   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的位置中。

 

更多關於字典(Dictionary)附屬指令碼的資訊請參考讀取和修改字典

 

注意:

 

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 ofrange")           return grid[(row * columns) + column]       }       set {           assert(indexIsValidForRow(row, column: column), "Index out ofrange")           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的最大長度


相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.