當(dāng)定義一個(gè)協(xié)議時(shí),有的時(shí)候聲明一個(gè)或多個(gè)關(guān)聯(lián)類型作為協(xié)議定義的一部分是非常有用的。一個(gè)關(guān)聯(lián)類型給定作用于協(xié)議部分的類型一個(gè)節(jié)點(diǎn)名(或別名)。作用于關(guān)聯(lián)類型上實(shí)際類型是不需要指定的,直到該協(xié)議接受。關(guān)聯(lián)類型被指定為typealias關(guān)鍵字。
這里是一個(gè)Container協(xié)議的例子,定義了一個(gè)ItemType關(guān)聯(lián)類型:
protocol Container {
typealias ItemType
mutating func append(item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
Container協(xié)議定義了三個(gè)任何容器必須支持的兼容要求:
append方法添加一個(gè)新item到容器里;count屬性獲取容器里items的數(shù)量,并返回一個(gè)Int值;Int索引值下標(biāo)可以檢索到每一個(gè)item。
這個(gè)協(xié)議沒(méi)有指定容器里item是如何存儲(chǔ)的或何種類型是允許的。這個(gè)協(xié)議只指定三個(gè)任何遵循Container類型所必須支持的功能點(diǎn)。一個(gè)遵循的類型也可以提供其他額外的功能,只要滿足這三個(gè)條件。
任何遵循Container協(xié)議的類型必須指定存儲(chǔ)在其里面的值類型,必須保證只有正確類型的items可以加進(jìn)容器里,必須明確可以通過(guò)其下標(biāo)返回item類型。
為了定義這三個(gè)條件,Container協(xié)議需要一個(gè)方法指定容器里的元素將會(huì)保留,而不需要知道特定容器的類型。Container協(xié)議需要指定任何通過(guò)append方法添加到容器里的值和容器里元素是相同類型,并且通過(guò)容器下標(biāo)返回的容器元素類型的值的類型是相同類型。
為了達(dá)到此目的,Container協(xié)議聲明了一個(gè)ItemType的關(guān)聯(lián)類型,寫作typealias ItemType。這個(gè)協(xié)議不會(huì)定義ItemType是什么的別名,這個(gè)信息留給了任何遵循協(xié)議的類型來(lái)提供。盡管如此,ItemType別名支持一種方法識(shí)別在一個(gè)容器里的items類型,以及定義一種使用在append方法和下標(biāo)中的類型,以便保證任何期望的Container的行為是強(qiáng)制性的。
這里是一個(gè)早前IntStack類型的非泛型版本,適用于遵循Container協(xié)議:
struct IntStack: Container {
// original IntStack implementation
var items = Int[]()
mutating func push(item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}
// conformance to the Container protocol
typealias ItemType = Int
mutating func append(item: Int) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> Int {
return items[i]
}
}
IntStack類型實(shí)現(xiàn)了Container協(xié)議的所有三個(gè)要求,在IntStack類型的每個(gè)包含部分的功能都滿足這些要求。
此外,IntStack指定了Container的實(shí)現(xiàn),適用的ItemType被用作Int類型。對(duì)于這個(gè)Container協(xié)議實(shí)現(xiàn)而言,定義 typealias ItemType = Int,將抽象的ItemType類型轉(zhuǎn)換為具體的Int類型。
感謝Swift類型參考,你不用在IntStack定義部分聲明一個(gè)具體的Int的ItemType。由于IntStack遵循Container協(xié)議的所有要求,只要通過(guò)簡(jiǎn)單的查找append方法的item參數(shù)類型和下標(biāo)返回的類型,Swift就可以推斷出合適的ItemType來(lái)使用。確實(shí),如果上面的代碼中你刪除了typealias ItemType = Int這一行,一切仍舊可以工作,因?yàn)樗宄闹繧temType使用的是何種類型。
你也可以生成遵循Container協(xié)議的泛型Stack類型:
struct Stack<T>: Container {
// original Stack<T> implementation
var items = T[]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
// conformance to the Container protocol
mutating func append(item: T) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> T {
return items[i]
}
}
這個(gè)時(shí)候,占位類型參數(shù)T被用作append方法的item參數(shù)和下標(biāo)的返回類型。Swift 因此可以推斷出被用作這個(gè)特定容器的ItemType的上一篇:Swift類型轉(zhuǎn)換下一篇:Swift函數(shù)