定義下標使用subscript關鍵字, 形式如下:
subscript(index: Int) -> Int {
get {
// 返回一個適當的 Int 類型的值
}
set(newValue) {
// 執行適當的賦值操作
}
}
只讀下標的實現 例:
struct TimesTable {
let multiplier: Int
subscript(index: Int) -> Int {
return multiplier * index
}
}
let threeTimesTable = TimesTable(multiplier: 3)
print("six times three is \(threeTimesTable[6])")
// 打印 "six times three is 18"
在上例中,創建了一個TimesTable實例,用來表示整數3的乘法表。數值3被傳遞給結構體的構造函數,作為實例成員multiplier的值。
下標用法
下標的確切含義取決于使用場景。下標通常作為訪問集合,列表或序列中元素的快捷方式。你可以針對自己特定的類或結構體的功能來自由地以最恰當的方式實現下標。
下標選項
- 下標可以接受任意數量的入參,并且這些入參可以是任意類型。下標的返回值也可以是任意類型。下標可以使用變量參數和可變參數,但不能使用輸入輸出參數,也不能給參數設置默認值。
- 一個類或結構體可以根據自身需要提供多個下標實現,使用下標時將通過入參的數量和類型進行區分,自動匹配合適的下標,這就是下標的重載。
雖然接受單一入參的下標是最常見的,但也可以根據情況定義接受多個入參的下標。例如下例定義了一個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) + column] = newValue
}
}
}
Matrix提供了一個接受兩個入參的構造方法,入參分別是rows和columns,創建了一個足夠容納rows * columns個Double類型的值的數組。通過傳入數組長度和初始值0.0到數組的構造器,將矩陣中每個位置的值初始化為0.0
你可以通過傳入合適的row和column的數量來構造一個新的Matrix實例:
var matrix = Matrix(rows: 2, columns: 2)
將row和column的值傳入下標來為矩陣設值,下標的入參使用逗號分隔:
matrix[0, 1] = 1.5
matrix[1, 0] = 3.2
Matrix下標的 getter 和 setter 中都含有斷言,用來檢查下標入參row和column的值是否有效。為了方便進行斷言,Matrix包含了一個名為indexIsValidForRow(_:column:)的便利方法,用來檢查入參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 的范圍