天天看點

Swift程式設計十三(下标)下标

案例代碼下載下傳

下标

類,結構和枚舉可以定義下标,下标是用于通路集合,清單或序列的成員元素的快捷方式。可以使用下标按索引設定和檢索值,而無需單獨的設定和檢索方法。例如,可以使用someArray[index]在Array執行個體中和使用someDictionary[key]在Dictionary執行個體通路元素。

可以為單個類型定義多個下标,并根據傳遞給下标的索引值的類型選擇要使用的相應下标重載。下标不限于單個次元,可以定義具有多個輸入參數的下标,以滿足自定義類型的需求。

下智語法

可以通過下标在執行個體名稱後面的方括号中寫入一個或多個值來查詢類型的執行個體。它們的文法類似于執行個體方法文法和計算屬性文法。使用subscript關鍵字編寫下标定義,并以與執行個體方法相同的方式指定一個或多個輸入參數和傳回類型。與執行個體方法不同,下标可以是讀寫或隻讀。此行為由getter和setter以與計算屬性相同的方式傳遞:

subscript(index: Int) -> Int {
    get {
        // 傳回一個适當的下标值
    }
    set(newValue) {
        // 執行相應的設值操作
    }
}
           

newValue類型與下标的傳回值相同。與計算屬性一樣,可以選擇不指定setter的(newValue)參數。newValue如果沒有自己提供,則setter提供一個預設參數。

與隻讀計算屬性一樣,可以通過删除get關鍵字及其大括号來簡化隻讀下标的聲明:

subscript(index: Int) -> Int {
    // 傳回一個适當的下标值
}
           

這是一個隻讀下标實作的示例,它定義了一個TimesTable表示整數n倍數表的結構:

struct TimesTable {
    let multiplier: Int
    subscript(index: Int) -> Int {
        return multiplier * index
    }
}
let threeTimesTable = TimesTable(multiplier: 3)
print(threeTimesTable[6])
           

在此示例中,TimesTable建立了一個新執行個體來表示3的倍數表。這通過将3的值傳遞給結構初始化作為執行個體multiplier參數的值來表示。

可以通過調用threeTimesTable下标來查詢執行個體,如調用中所示threeTimesTable[6]。這将請求3的倍數表中的第六個條目,該表傳回值18或3的6倍。

注意: 一個倍數表是基于一個固定的數學規則。設定threeTimesTable[someIndex]為新值是不合适的,是以TimesTable下标被定義為隻讀下标。

下标用法

“下标”的确切含義取決于使用它的上下文。下标通常用作通路集合,清單或序列中的成員元素的快捷方式。可以以最合适的方式為特定類或結構的功能實作下标。

例如,Swift的Dictionary類型實作了一個下标來設定和檢索存儲在Dictionary執行個體中的值。可以通過在下标括号中提供字典的鍵類型的鍵,并将字典的值類型的值配置設定給下标來設定字典中的值:

var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
numberOfLegs["bird"] = 2
           

上面的示例定義了一個名為numberOfLegs的變量,并使用包含三個鍵值對的字典文字對其進行初始化。numberOfLegs推斷字典的類型是[String: Int]。建立字典後,此示例使用下标配置設定向字典添加鍵String"bird"和值Int2。

有關Dictionary下标的詳細資訊,請參閱通路和修改字典。

注意: Swift的Dictionary類型将其鍵值下标實作為擷取并傳回可選類型的下标。對于上面的numberOfLegs字典,鍵值下标采用并傳回Int?類型的值,或“optional int”類型。該Dictionary類型使用可選的下标類型來模拟不是每個鍵都有值的事實,并通過為該鍵指派為nil來删除鍵的值提供一種方法。

下标選項

下标可以采用任意數量的輸入參數,這些輸入參數可以是任何類型。下标也可以傳回任何類型。下标可以使用可變參數,但它們不能使用輸入輸出參數或提供預設參數值。

類或結構可以根據需要提供盡可能多的下标實作,并且将基于在使用下标處括号内包含的值或值的類型來推斷要使用的适當下标。多個下标的這種定義稱為下标重載。

雖然下标采用單個參數是最常見的,但如果适合你的類型,也可以定義帶有多個參數的下标。以下示例定義了一個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(repeating: 0.0, count: rows*columns)
    }
    func indexIsValid(row: Int, colunm: Int) -> Bool {
        return row >= 0 && row < rows && colunm >= 0 && colunm < columns
    }
    subscript(row: Int, column: Int) -> Double {
        get {
            assert(indexIsValid(row: row, colunm: column), "Index out of range")
            return grid[row*columns + column]
        }
        set {
            assert(indexIsValid(row: row, colunm: column), "Index out of range")
            grid[row*columns + column] = newValue
        }
    }
}
           

Matrix提供了采用兩個稱為rows和columns參數的初始化方法,并建立一個數組,它是大到足以存儲rows * columns個Double類型的值。矩陣中的每個位置都給出初始值0.0。為此,将數組的大小和初始單元格值0.0傳遞給數組初始值設定項,該數組初始值設定項建立并初始化正确大小的新數組。在建立具有預設值的數組中更詳細地描述了此初始化程式。

可以通過将适當的行和列計數傳遞給Matrix初始化設定項來構造新執行個體:

var matrix = Matrix(rows: 2, columns: 2)
           

上面的示例建立了一個Matrix包含兩行和兩列的新執行個體。此Matrix執行個體的數組實際上是矩陣的扁平版本,從左上角到右下角讀取:

Swift程式設計十三(下标)下标

可以通過将行和列值傳遞到下标中來設定矩陣中的值,用逗号分隔:

matrix[0, 1] = 1.5
matrix[1, 0] = 3.2
           

這兩個語句調用下标的setter來設定矩陣右上角的位置(其中row是0和column是1)為1.5,并在左下角位置(其中row是1和column是0)設定為3.2:

Swift程式設計十三(下标)下标

Matrix下标的getter和setter都包含一個斷言,以檢查标的row和column值是有效的。為了協助這些斷言,Matrix包括一個被稱為indexIsValid(row:column:)便捷方法,檢查是否所請求的row和column處于矩陣的邊界内:

func indexIsValid(row: Int, colunm: Int) -> Bool {
        return row >= 0 && row < rows && colunm >= 0 && colunm < columns
    }
           

如果嘗試通路矩陣邊界之外的下标,則會觸發斷言:

let someValue = matrix[2, 2]