下標(biāo)腳本允許任意數(shù)量的入?yún)⑺饕⑶颐總€(gè)入?yún)㈩愋鸵矝](méi)有限制。下標(biāo)腳本的返回值也可以是任何類型。下標(biāo)腳本可以使用變量參數(shù)和可變參數(shù),但使用寫(xiě)入讀出(in-out)參數(shù)或給參數(shù)設(shè)置默認(rèn)值都是不允許的。
一個(gè)類或結(jié)構(gòu)體可以根據(jù)自身需要提供多個(gè)下標(biāo)腳本實(shí)現(xiàn),在定義下標(biāo)腳本時(shí)通過(guò)入?yún)€(gè)類型進(jìn)行區(qū)分,使用下標(biāo)腳本時(shí)會(huì)自動(dòng)匹配合適的下標(biāo)腳本實(shí)現(xiàn)運(yùn)行,這就是下標(biāo)腳本的重載。
一個(gè)下標(biāo)腳本入?yún)⑹亲畛R?jiàn)的情況,但只要有合適的場(chǎng)景也可以定義多個(gè)下標(biāo)腳本入?yún)?。如下例定義了一個(gè)Matrix結(jié)構(gòu)體,將呈現(xiàn)一個(gè)Double類型的二維矩陣。Matrix結(jié)構(gòu)體的下標(biāo)腳本需要兩個(gè)整型參數(shù):
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提供了一個(gè)兩個(gè)入?yún)⒌臉?gòu)造方法,入?yún)⒎謩e是rows和columns,創(chuàng)建了一個(gè)足夠容納rows * columns個(gè)數(shù)的Double類型數(shù)組。為了存儲(chǔ),將數(shù)組的大小和數(shù)組每個(gè)元素初始值0.0,都傳入數(shù)組的構(gòu)造方法中來(lái)創(chuàng)建一個(gè)正確大小的新數(shù)組。關(guān)于數(shù)組的構(gòu)造方法和析構(gòu)方法請(qǐng)參考創(chuàng)建并且構(gòu)造一個(gè)數(shù)組。
你可以通過(guò)傳入合適的row和column的數(shù)量來(lái)構(gòu)造一個(gè)新的Matrix實(shí)例:
var matrix = Matrix(rows: 2, columns: 2)
上例中創(chuàng)建了一個(gè)新的兩行兩列的Matrix實(shí)例。在閱讀順序從左上到右下的Matrix實(shí)例中的數(shù)組實(shí)例grid是矩陣二維數(shù)組的扁平化存儲(chǔ):
// 示意圖
grid = [0.0, 0.0, 0.0, 0.0]
col0 col1
row0 [0.0, 0.0,
row1 0.0, 0.0]
將值賦給帶有row和column下標(biāo)腳本的matrix實(shí)例表達(dá)式可以完成賦值操作,下標(biāo)腳本入?yún)⑹褂枚禾?hào)分割
matrix[0, 1] = 1.5
matrix[1, 0] = 3.2
上面兩條語(yǔ)句分別讓matrix的右上值為 1.5,坐下值為 3.2:
[0.0, 1.5,
3.2, 0.0]
Matrix下標(biāo)腳本的getter和setter中同時(shí)調(diào)用了下標(biāo)腳本入?yún)⒌?code style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 14px; padding: 0px 5px; color: rgb(199, 37, 78); background-color: rgb(248, 248, 248); white-space: nowrap; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; margin: 0px 2px; border: 1px solid rgb(234, 234, 234);">row和column是否有效的判斷。為了方便進(jìn)行斷言,Matrix包含了一個(gè)名為indexIsValid的成員方法,用來(lái)確認(rèn)入?yún)⒌?code style="box-sizing: border-box; -webkit-tap-highlight-color: transparent; -webkit-font-smoothing: antialiased; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 14px; padding: 0px 5px; color: rgb(199, 37, 78); background-color: rgb(248, 248, 248); white-space: nowrap; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; margin: 0px 2px; border: 1px solid rgb(234, 234, 234);">row或column值是否會(huì)造成數(shù)組越界:
func indexIsValidForRow(row: Int, column: Int) -> Bool {
return row >= 0 && row < rows && column >= 0 && column < columns
}
斷言在下標(biāo)腳本越界時(shí)觸發(fā):
let someValue = matrix[2, 2]
// 斷言將會(huì)觸發(fā),因?yàn)?[2, 2] 已經(jīng)超過(guò)了matrix的最大長(zhǎng)度