本頁包含內(nèi)容:
[TOC]
下標(biāo)可以定義在類、結(jié)構(gòu)體和枚舉中堕仔,是訪問集合擂橘、列表和序列中元素的快捷方式,可以使用下標(biāo)的索引摩骨,設(shè)置和獲取值贝室,而不需要再調(diào)用對應(yīng)的存取方法。舉例來說仿吞,用下標(biāo)訪問一個Array
實(shí)例中的元素可以寫作someArray[index]
滑频,訪問Dictionary
實(shí)例中的元素可以寫作someDictionary[key]
。
一個類型可以定義多個下標(biāo)唤冈,通過不同索引類型進(jìn)行重載峡迷。下標(biāo)不限于一維,你可以定義具有多個入?yún)⒌南聵?biāo)滿足自定義類型的需求你虹。
下標(biāo)語法
下標(biāo)允許你通過在實(shí)例名稱后面的方括號中傳入一個或者多個索引值類對實(shí)例進(jìn)行存取绘搞。語法類似實(shí)例方法和計算型語法的混合。與定義實(shí)例方法類似傅物,定義下標(biāo)使用subscript
關(guān)鍵字夯辖,指定一個或多個輸入?yún)?shù)和返回類型;與實(shí)例方法不同的使董饰,下標(biāo)可以設(shè)定為讀寫或只讀蒿褂。這種行為由getter和setter實(shí)現(xiàn),有點(diǎn)類似計算型屬性:
subscript(index: Int) -> Int {
get {
// 返回一個適當(dāng)?shù)腎nt類型值
}
set(newValue) {
// 執(zhí)行適當(dāng)?shù)馁x值操作
}
}
newValue
的類型和下標(biāo)的返回類型相同卒暂,如同計算型屬性啄栓,可以不指定setter的參數(shù),如果不指定參數(shù)也祠,setter會提供一個名為newValue
的默認(rèn)參數(shù)昙楚。
如同只讀計算型屬性,可以省略只讀下標(biāo)的get
關(guān)鍵字:
subscript(index: Int) -> Int {
// 返回一個適當(dāng)?shù)腎nt類型的值
}
下面的代碼演示了只讀下標(biāo)的實(shí)現(xiàn)诈嘿,這里定義了一個TimesTable
結(jié)構(gòu)體堪旧,用來表示傳入整數(shù)的乘法表:
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"
在上例中削葱,創(chuàng)建了一個TimesTable
實(shí)例,用來表示整數(shù)3
的乘法表淳梦。數(shù)值3
被傳遞給結(jié)構(gòu)體的構(gòu)造函數(shù)佩耳,作為實(shí)例成員multiplier
的值。
你可以通過下標(biāo)訪問threeTimesTable
實(shí)例谭跨,例如上面演示的threeTimesTable[6]
干厚。這條語句查詢了3
的乘法表中的第六個元素,返回3
的6
倍即18
螃宙。
注意:
TimesTable
例子基于一個固定的數(shù)學(xué)公式蛮瞄,對threeTimesTable[someIndex]
進(jìn)行賦值操作并不合適,因此下標(biāo)定義為只讀的谆扎。
下標(biāo)用法
下標(biāo)的確切含義取決于使用場景挂捅。下標(biāo)通常作為訪問集合、列表和序列中元素的快捷方式堂湖。你可以針對自己特定的類或者結(jié)構(gòu)體的功能來自由地義最恰當(dāng)?shù)姆绞綄?shí)現(xiàn)下標(biāo)闲先。
例如,Swift的Dictionary
類型實(shí)現(xiàn)下標(biāo)用于對其實(shí)例中存儲的值進(jìn)行存取操作无蜂。為字典設(shè)置值時伺糠,在下標(biāo)中使用和字典的鍵類型相同的鍵,并把一個和字典的值類型的值賦給這個下標(biāo):
var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
numberOfLegs["bird"] = 2
上例定義一個名為numberOfLegs
的變量斥季,并用一個包含三對鍵值的字典字面量初始化它训桶。numberOfLegs
字典的類型被推斷為[String: Int]
。字典創(chuàng)建完成后酣倾,該例子通過下標(biāo)將String
類型的鍵bird
和Int
類型的值2
添加到字典中舵揭。
注意:Swift的
Dictionary
類型的下標(biāo)接受并返回可選類型的值。上例中的numberOfLegs
字典通過下標(biāo)返回的是一個Int?
或者說“可選的int”躁锡。Dictionary
類型之所以如此實(shí)現(xiàn)下標(biāo)午绳,是因?yàn)椴皇敲總€鍵都有個對應(yīng)的值,同時這也提供了一種通過鍵刪除對應(yīng)值的方式映之,只需將鍵對應(yīng)的值賦值為nil
即可拦焚。
下標(biāo)選項(xiàng)
下標(biāo)可以接受任意數(shù)量的入?yún)ⅲ⑶疫@些入?yún)⒖梢允侨我忸愋吞枰健O聵?biāo)的返回值也可以是任意類型耕漱。下標(biāo)也可以使用變量參數(shù)可變參數(shù)算色,但不能使用輸入輸出參數(shù)抬伺,也不能給參數(shù)設(shè)置默認(rèn)值。
一個類或結(jié)構(gòu)體可以根據(jù)自身需要提供多個下標(biāo)實(shí)現(xiàn)灾梦,使用下標(biāo)時將通過入?yún)⒌臄?shù)量和類型進(jìn)行區(qū)分峡钓,自動匹配合適的下標(biāo)妓笙,這就是下標(biāo)的重載。
雖然接受單一入?yún)⒌南聵?biāo)時最常見的能岩,但也可以根據(jù)情況定義接受多個入?yún)⒌南聵?biāo)寞宫。
例如下例定義了一個Matrix
結(jié)構(gòu)體,用于表示一個Double
類型的二維矩陣拉鹃。Matrix
結(jié)構(gòu)體的下標(biāo)接受兩個整型參數(shù):
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, column: Int) -> Bool {
return row >=0 && row < rows && column >=0 && column < columns
}
subscript(row: Int, column: Int) -> Double {
set {
assert(indexIsValid(row: row, column: column), "Index out of range")
grid[(row * columns) + column] = newValue
}
get {
assert(indexIsValid(row: row, column: column), "Index out of range")
return grid[(row * columns) + column]
}
}
}
Matrix
提供了一個接受兩個入?yún)⒌臉?gòu)造方法辈赋,入?yún)⒎謩e是rows
和columns
,創(chuàng)建了一個足夠容納rows * columns
個Double
類型的值的數(shù)組膏燕。通過傳入數(shù)組長度和初始值0.0
到數(shù)組的構(gòu)造器钥屈,將矩陣中每個位置的值初始化為0.0
赋咽。
你可以通過傳入合適的row
和column
的數(shù)量來構(gòu)造一個新的Matrix
實(shí)例:
var matrix = Matrix(rows: 2, columns: 2)
上例中創(chuàng)建了一個Matrix
實(shí)例來表示兩行兩列的矩陣桩了。該Matrix
實(shí)例的grid
數(shù)組按照從左上到右下的閱讀順序?qū)⒕仃嚤馄交鎯Γ?/p>
[圖片上傳失敗...(image-bed4b2-1520405596285)]
將row
和column
的值傳入下標(biāo)來為矩陣設(shè)值塞淹,下標(biāo)的入?yún)⑹褂枚禾柗指簦?/p>
matrix[0, 1] = 1.5
matrix[1, 0] = 3.2
上面兩條語句分別調(diào)用下標(biāo)的 setter 將矩陣右上角位置(即row
為0
更米、column
為1
的位置)的值設(shè)置為1.5
铁瞒,將矩陣左下角位置(即row
為1
萎坷、column
為0
的位置)的值設(shè)置為3.2
:
[圖片上傳失敗...(image-c75ac0-1520405596285)]
Matrix
下標(biāo)的 getter 和 setter 中都含有斷言稀余,用來檢查下標(biāo)入?yún)?code>row和column
的值是否有效国葬。為了方便進(jìn)行斷言及舍,Matrix
包含了一個名為indexIsValid(row:column:)
的便利方法未辆,用來檢查入?yún)?code>row和column
的值是否在矩陣范圍內(nèi):
func indexIsValid(row: Int, column: Int) -> Bool {
return row >= 0 && row < rows && column >= 0 && column < columns
}
斷言在下標(biāo)越界時觸發(fā):
let someValue = matrix[2, 2]
// 斷言將會觸發(fā),因?yàn)?[2, 2] 已經(jīng)超過了 matrix 的范圍