泛型代碼 能夠根據(jù)自定義的需求,編寫(xiě)出適用于任意類型、靈活可重用的函數(shù)及類型。避免代碼的重復(fù)允瞧,用一種清晰和抽象的方式來(lái)表達(dá)代碼的意圖。
Swift 的 Array
和 Dictionary
都是泛型集合蛮拔。你可以創(chuàng)建一個(gè) Int
數(shù)組述暂,也可創(chuàng)建一個(gè) String
數(shù)組,甚至可以是任意其他 Swift 類型的數(shù)組语泽。同樣的贸典,你也可以創(chuàng)建存儲(chǔ)任意指定類型的字典。
泛型所解決的問(wèn)題
下面是一個(gè)標(biāo)準(zhǔn)的非泛型函數(shù) swapTwoInts(_:_:)
踱卵,用來(lái)交換兩個(gè) Int
值:
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
它只能交換 Int
值,如果你想要交換兩個(gè) String
值或者 Double
值,就不得不寫(xiě)更多的函數(shù)惋砂,例如 swapTwoStrings(_:_:)
和 swapTwoDoubles(_:_:)
妒挎,如下所示:
func swapTwoStrings(_ a: inout String, _ b: inout String) {
let temporaryA = a
a = b
b = temporaryA
}
func swapTwoDoubles(_ a: inout Double, _ b: inout Double) {
let temporaryA = a
a = b
b = temporaryA
}
在實(shí)際應(yīng)用中,通常需要一個(gè)更實(shí)用更靈活的函數(shù)來(lái)交換兩個(gè)任意類型的值西饵,幸運(yùn)的是酝掩,泛型代碼幫你解決了這種問(wèn)題。(這些函數(shù)的泛型版本已經(jīng)在下面定義好了眷柔。)
注意
在上面三個(gè)函數(shù)中期虾,a
和b
類型必須相同。如果a
和b
類型不同驯嘱,那它們倆就不能互換值镶苞。Swift 是類型安全的語(yǔ)言,所以它不允許一個(gè)String
類型的變量和一個(gè)Double
類型的變量互換值鞠评。試圖這樣做將導(dǎo)致編譯錯(cuò)誤茂蚓。
泛型函數(shù)
泛型函數(shù)可以適用于任何類型,下面的 swapTwoValues(_:_:)
函數(shù)是上面三個(gè)函數(shù)的泛型版本:
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temporaryA = a
a = b
b = temporaryA
}
泛型函數(shù)名后面跟著占位類型名(這里用字母 T
來(lái)表示)剃幌,并用尖括號(hào)括起來(lái)(<T>
)聋涨。占位類型名沒(méi)指明必須是什么類型,但指明了 a
和 b
必須是同一類型 T
负乡, 函數(shù)在調(diào)用時(shí)才會(huì)根據(jù)所傳入的實(shí)際類型決定 T
所代表的類型牍白。
var someInt = 3
var anotherInt = 107
swapTwoValues(&someInt, &anotherInt)
// someInt 現(xiàn)在 107, and anotherInt 現(xiàn)在 3
var someString = "hello"
var anotherString = "world"
swapTwoValues(&someString, &anotherString)
// someString 現(xiàn)在 "world", and anotherString 現(xiàn)在 "hello"
注意
上面定義的swapTwoValues(_:_:)
函數(shù)是受swap(_:_:)
函數(shù)啟發(fā)而實(shí)現(xiàn)的。后者存在于 Swift 標(biāo)準(zhǔn)庫(kù)抖棘,你可以在你的應(yīng)用程序中使用它淹朋。如果你在代碼中需要類似swapTwoValues(_:_:)
函數(shù)的功能,你可以使用已存在的swap(_:_:)
函數(shù)钉答。
類型參數(shù)
在上面的 swapTwoValues(_:_:)
例子中础芍,占位類型 T
是類型參數(shù)的一個(gè)例子。類型參數(shù)指定并命名一個(gè)占位類型数尿,并且緊隨在函數(shù)名后面仑性,使用一對(duì)尖括號(hào)括起來(lái)(例如 <T>
)。
一旦一個(gè)類型參數(shù)被指定右蹦,你可以用它來(lái)定義一個(gè)函數(shù)的參數(shù)類型(例如 swapTwoValues(_:_:)
函數(shù)中的參數(shù) a
和 b
)诊杆,或者作為函數(shù)的返回類型,還可以用作函數(shù)主體中的注釋類型何陆。在這些情況下晨汹,類型參數(shù)會(huì)在函數(shù)調(diào)用時(shí)被實(shí)際類型所替換。
你可提供多個(gè)類型參數(shù)贷盲,將它們都寫(xiě)在尖括號(hào)中淘这,用逗號(hào)分開(kāi)剥扣。
命名類型參數(shù)
在大多數(shù)情況下,類型參數(shù)具有一個(gè)描述性名字铝穷,例如 Dictionary<Key, Value>
中的 Key
和 Value
钠怯,以及 Array<Element>
中的 Element
,這可以告訴閱讀代碼的人這些類型參數(shù)和泛型函數(shù)之間的關(guān)系曙聂。然而晦炊,當(dāng)它們之間沒(méi)有有意義的關(guān)系時(shí),通常使用單個(gè)字母來(lái)命名宁脊,例如 T
断国、U
、V
榆苞,正如上面演示的 swapTwoValues(_:_:)
函數(shù)中的 T
一樣稳衬。
注意
請(qǐng)始終使用大寫(xiě)字母開(kāi)頭的駝峰命名法(例如T
和MyTypeParameter
)來(lái)為類型參數(shù)命名,以表明它們是占位類型语稠,而不是一個(gè)值宋彼。
泛型類型
除了泛型函數(shù),Swift 還允許你定義泛型類型仙畦。這些自定義類输涕、結(jié)構(gòu)體和枚舉可以適用于任何類型,類似于 Array
和 Dictionary
慨畸。
這部分內(nèi)容將向你展示如何編寫(xiě)一個(gè)名為 Stack
(棧)的泛型集合類型莱坎。棧是一系列值的有序集合,和 Array
類似寸士,但它相比 Swift 的 Array
類型有更多的操作限制檐什。數(shù)組允許在數(shù)組的任意位置插入新元素或是刪除其中任意位置的元素。而棧只允許在集合的末端添加新的元素(稱之為入棧)弱卡。類似的乃正,棧也只能從末端移除元素(稱之為出棧)。
注意
棧的概念已被UINavigationController
類用來(lái)構(gòu)造視圖控制器的導(dǎo)航結(jié)構(gòu)婶博。你通過(guò)調(diào)用UINavigationController
的pushViewController(_:animated:)
方法來(lái)添加新的視圖控制器到導(dǎo)航棧瓮具,通過(guò)popViewControllerAnimated(_:)
方法來(lái)從導(dǎo)航棧中移除視圖控制器。每當(dāng)你需要一個(gè)嚴(yán)格的“后進(jìn)先出”方式來(lái)管理集合凡人,棧都是最實(shí)用的模型名党。
下面展示了如何編寫(xiě)一個(gè)非泛型版本的棧,以 Int
型的棧為例:
struct IntStack {
var items = [Int]()
mutating func push(_ item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}
}
上面的 IntStack
結(jié)構(gòu)體只能用于 Int
類型挠轴。不過(guò)传睹,可以定義一個(gè)泛型 Stack
結(jié)構(gòu)體,從而能夠處理任意類型的值岸晦。
下面是相同代碼的泛型版本:
struct Stack<Element> {
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
}
例如欧啤,要?jiǎng)?chuàng)建一個(gè) String
類型的棧睛藻,可以寫(xiě)成 Stack<String>()
:
var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")
stackOfStrings.push("cuatro")
// 棧中現(xiàn)在有 4 個(gè)字符串
移除并返回棧頂部的值 "cuatro"
,即將其出棧:
let fromTheTop = stackOfStrings.pop()
// fromTheTop 的值為 "cuatro"堂油,現(xiàn)在棧中還有 3 個(gè)字符串
擴(kuò)展一個(gè)泛型類型
當(dāng)你擴(kuò)展一個(gè)泛型類型的時(shí)候修档,你并不需要在擴(kuò)展的定義中提供類型參數(shù)列表碧绞。原始類型定義中聲明的類型參數(shù)列表在擴(kuò)展中可以直接使用府框,并且這些來(lái)自原始類型中的參數(shù)名稱會(huì)被用作原始定義中類型參數(shù)的引用。
下面的例子擴(kuò)展了泛型類型 Stack
讥邻,為其添加了一個(gè)名為 topItem
的只讀計(jì)算型屬性迫靖,它將會(huì)返回當(dāng)前棧頂端的元素而不會(huì)將其從棧中移除:
extension Stack {
var topItem: Element? {
return items.isEmpty ? nil : items[items.count - 1]
}
}
類型約束
swapTwoValues(_:_:)
函數(shù)和 Stack
類型可以作用于任何類型。需要時(shí)兴使,類型約束可以指定一個(gè)類型參數(shù)必須繼承自指定類系宜,或者符合一個(gè)特定的協(xié)議或協(xié)議組合。
例如发魄,Swift 的 Dictionary
類型對(duì)字典的鍵的類型做了些限制盹牧。字典的鍵的類型必須是可哈希(hashable
)的。這是為了便于檢查字典是否已經(jīng)包含某個(gè)特定鍵的值励幼。字典的鍵類型上汰寓,要求必須符合 Hashable
協(xié)議。所有的 Swift 基本類型(例如 String
苹粟、Int
有滑、Double
和 Bool
)默認(rèn)都是可哈希的。
類型約束語(yǔ)法
你可以在一個(gè)類型參數(shù)名后面放置一個(gè)類名或者協(xié)議名嵌削,并用冒號(hào)進(jìn)行分隔毛好,來(lái)定義類型約束,它們將成為類型參數(shù)列表的一部分苛秕。對(duì)泛型函數(shù)添加類型約束的基本語(yǔ)法如下所示(作用于泛型類型時(shí)的語(yǔ)法與之相同):
func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
// 這里是泛型函數(shù)的函數(shù)體部分
}
上面這個(gè)函數(shù)有兩個(gè)類型參數(shù)肌访。第一個(gè)類型參數(shù) T
,有一個(gè)要求 T
必須是 SomeClass
子類的類型約束艇劫;第二個(gè)類型參數(shù) U
吼驶,有一個(gè)要求 U
必須符合 SomeProtocol
協(xié)議的類型約束。
類型約束實(shí)踐
下面非泛型函數(shù)港准,功能是在一個(gè) String
數(shù)組中查找給定 String
值的索引旨剥。若查找到匹配的字符串,findIndex(ofString:in:)
函數(shù)返回該字符串在數(shù)組中的索引值浅缸,否則返回 nil
:
func findIndex(ofString valueToFind: String, in array: [String]) -> Int? {
for (index, value) in array.enumerated() {
if value == valueToFind {
return index
}
}
return nil
}
let strings = ["cat", "dog", "llama", "parakeet", "terrapin"]
if let foundIndex = findIndex(ofString: "llama", in: strings) {
print("The index of llama is \(foundIndex)")
}
// 打印 “The index of llama is 2”
findIndex(ofString:in:)
函數(shù)的泛型版本 轨帜。
func findIndex<T>(of valueToFind: T, in array:[T]) -> Int? {
for (index, value) in array.enumerated() {
if value == valueToFind {
return index
}
}
return nil
}
上面所寫(xiě)的函數(shù)無(wú)法通過(guò)編譯。問(wèn)題出在相等性檢查上衩椒,即 "if value == valueToFind
"蚌父。不是所有的 Swift 類型都可以用等式符(==
)進(jìn)行比較哮兰。比如說(shuō),如果你創(chuàng)建一個(gè)自定義的類或結(jié)構(gòu)體來(lái)表示一個(gè)復(fù)雜的數(shù)據(jù)模型苟弛,那么 Swift 無(wú)法猜到對(duì)于這個(gè)類或結(jié)構(gòu)體而言“相等”意味著什么喝滞。正因如此,這部分代碼無(wú)法保證適用于每個(gè)可能的類型 T
膏秫,當(dāng)你試圖編譯這部分代碼時(shí)會(huì)出現(xiàn)相應(yīng)的錯(cuò)誤右遭。
Swift 標(biāo)準(zhǔn)庫(kù)中定義了一個(gè) Equatable
協(xié)議,該協(xié)議要求任何遵循該協(xié)議的類型必須實(shí)現(xiàn)等式符(==
)及不等符(!=
)缤削,從而能對(duì)該類型的任意兩個(gè)值進(jìn)行比較窘哈。所有的 Swift 標(biāo)準(zhǔn)類型自動(dòng)支持 Equatable
協(xié)議。
你可以定義一個(gè) Equatable
類型約束作為類型參數(shù)定義的一部分:
func findIndex<T: Equatable>(of valueToFind: T, in array:[T]) -> Int? {
for (index, value) in array.enumerated() {
if value == valueToFind {
return index
}
}
return nil
}
let doubleIndex = findIndex(of: 9.3, in: [3.14159, 0.1, 0.25])
// doubleIndex 類型為 Int?亭敢,其值為 nil滚婉,因?yàn)?9.3 不在數(shù)組中
let stringIndex = findIndex(of: "Andrea", in: ["Mike", "Malcolm", "Andrea"])
// stringIndex 類型為 Int?,其值為 2
關(guān)聯(lián)類型
定義一個(gè)協(xié)議時(shí)帅刀,有的時(shí)候聲明一個(gè)或多個(gè)關(guān)聯(lián)類型作為協(xié)議定義的一部分將會(huì)非常有用让腹。關(guān)聯(lián)類型為協(xié)議中的某個(gè)類型提供了一個(gè)占位名(或者說(shuō)別名),其代表的實(shí)際類型在協(xié)議被采納時(shí)才會(huì)被指定扣溺。你可以通過(guò) associatedtype
關(guān)鍵字來(lái)指定關(guān)聯(lián)類型骇窍。
關(guān)聯(lián)類型實(shí)踐
下面例子定義了一個(gè) Container
協(xié)議,該協(xié)議定義了一個(gè)關(guān)聯(lián)類型 ItemType
:
protocol Container {
associatedtype ItemType
mutating func append(_ item: ItemType) //添加一個(gè)新元素到容器里
var count: Int { get } //獲取容器中元素的數(shù)量
subscript(i: Int) -> ItemType { get } //通過(guò) 下標(biāo)檢索對(duì)應(yīng)元素
}
下面是先前的非泛型的 IntStack
類型娇妓,這一版本采納并符合了 Container
協(xié)議:
struct IntStack: Container {
// IntStack 的原始實(shí)現(xiàn)部分
var items = [Int]()
mutating func push(_ item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}
// Container 協(xié)議的實(shí)現(xiàn)部分
typealias ItemType = Int
mutating func append(_ item: Int) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> Int {
return items[i]
}
}
你也可以讓泛型 Stack
結(jié)構(gòu)體遵從 Container
協(xié)議:
struct Stack<Element>: Container {
// Stack<Element> 的原始實(shí)現(xiàn)部分
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
// Container 協(xié)議的實(shí)現(xiàn)部分
mutating func append(_ item: Element) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> Element {
return items[i]
}
}
Swift 的類型推斷像鸡,占位類型參數(shù) Element
被用作 append(_:)
方法的 item
參數(shù)和下標(biāo)的返回類型」。可以推斷出 Element
的類型即是 ItemType
的類型只估。
通過(guò)擴(kuò)展一個(gè)存在的類型來(lái)指定關(guān)聯(lián)類型
“通過(guò)擴(kuò)展添加協(xié)議一致性” 中描述了如何利用擴(kuò)展讓一個(gè)已存在的類型符合一個(gè)協(xié)議,這包括使用了關(guān)聯(lián)類型的協(xié)議着绷。
Swift 的 Array
類型已經(jīng)提供 append(_:)
方法蛔钙,一個(gè) count
屬性,以及一個(gè)接受 Int
類型索引值的下標(biāo)用以檢索其元素荠医。這三個(gè)功能都符合 Container
協(xié)議的要求吁脱,也就意味著你只需簡(jiǎn)單地聲明 Array
采納該協(xié)議就可以擴(kuò)展 Array
,使其遵從 Container
協(xié)議彬向。你可以通過(guò)一個(gè)空擴(kuò)展來(lái)實(shí)現(xiàn)這點(diǎn)兼贡,正如“通過(guò)擴(kuò)展采納協(xié)議”中的描述:
extension Array: Container {}
如同上面的泛型 Stack
結(jié)構(gòu)體一樣,Array
的 append(_:)
方法和下標(biāo)確保了 Swift 可以推斷出 ItemType
的類型娃胆。定義了這個(gè)擴(kuò)展后遍希,你可以將任意 Array
當(dāng)作 Container
來(lái)使用。
約束關(guān)聯(lián)類型
你可以給協(xié)議里的關(guān)聯(lián)類型添加類型注釋里烦,讓遵守協(xié)議的類型必須遵循這個(gè)約束條件凿蒜。
例如禁谦,下面的代碼定義了一個(gè) Item
必須遵循 Equatable
的 Container
類型:
protocol Container {
associatedtype Item: Equatable
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }
}
為了遵守了 Container
協(xié)議,Item 類型也必須遵守 Equatable
協(xié)議废封。
泛型 where 語(yǔ)句
“類型約束” 讓你能夠?yàn)榉盒秃瘮?shù)州泊,下標(biāo),類型的類型參數(shù)定義一些強(qiáng)制要求漂洋。
可以在參數(shù)列表中通過(guò) where
子句為關(guān)聯(lián)類型定義約束遥皂。通過(guò) where
子句要求一個(gè)關(guān)聯(lián)類型遵從某個(gè)特定的協(xié)議,以及某個(gè)特定的類型參數(shù)和關(guān)聯(lián)類型必須類型相同氮发。你可以通過(guò)將 where
關(guān)鍵字緊跟在類型參數(shù)列表后面來(lái)定義 where
子句渴肉,where
子句后跟一個(gè)或者多個(gè)針對(duì)關(guān)聯(lián)類型的約束冗懦,以及一個(gè)或多個(gè)類型參數(shù)和關(guān)聯(lián)類型間的相等關(guān)系爽冕。你可以在函數(shù)體或者類型的大括號(hào)之前添加 where 子句。
檢查兩個(gè) Container
實(shí)例是否包含相同順序的相同元素披蕉,被檢查的兩個(gè) Container
可以不是相同類型的容器(雖然它們可以相同)颈畸,但它們必須擁有相同類型的元素。這個(gè)要求通過(guò)一個(gè)類型約束以及一個(gè) where
子句來(lái)表示:
func allItemsMatch<C1: Container, C2: Container>
(_ someContainer: C1, _ anotherContainer: C2) -> Bool
where C1.ItemType == C2.ItemType, C1.ItemType: Equatable {
// 檢查兩個(gè)容器含有相同數(shù)量的元素
if someContainer.count != anotherContainer.count {
return false
}
// 檢查每一對(duì)元素是否相等
for i in 0..<someContainer.count {
if someContainer[i] != anotherContainer[i] {
return false
}
}
// 所有元素都匹配没讲,返回 true
return true
}
這個(gè)函數(shù)的類型參數(shù)列表定義了對(duì)兩個(gè)類型參數(shù)的要求:
-
C1
必須符合Container
協(xié)議(寫(xiě)作C1: Container
)眯娱。 -
C2
必須符合Container
協(xié)議(寫(xiě)作C2: Container
)。 -
C1
的ItemType
必須和C2
的ItemType
類型相同(寫(xiě)作C1.ItemType == C2.ItemType
)爬凑。 -
C1
的ItemType
必須符合Equatable
協(xié)議(寫(xiě)作C1.ItemType: Equatable
)徙缴。
使用:
var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")
var arrayOfStrings = ["uno", "dos", "tres"]
if allItemsMatch(stackOfStrings, arrayOfStrings) {
print("All items match.")
} else {
print("Not all items match.")
}
// 打印 “All items match.”
具有泛型 where 子句的擴(kuò)展
你也可以使用泛型 where
子句作為擴(kuò)展的一部分∴倚牛基于以前的例子于样,下面的示例擴(kuò)展了泛型 Stack
結(jié)構(gòu)體,添加一個(gè) isTop(_:)
方法潘靖。
extension Stack where Element: Equatable {
func isTop(_ item: Element) -> Bool {
//檢查這個(gè)棧是不是空的
guard let topItem = items.last else {
return false
}
return topItem == item
}
}
如果嘗試在其元素不符合 Equatable 協(xié)議的棧上調(diào)用 isTop(_:)
方法穿剖,則會(huì)收到編譯時(shí)錯(cuò)誤。
struct NotEquatable { }
var notEquatableStack = Stack<NotEquatable>()
let notEquatableValue = NotEquatable()
notEquatableStack.push(notEquatableValue)
notEquatableStack.isTop(notEquatableValue) // 報(bào)錯(cuò)
你可以使用泛型 where
子句去擴(kuò)展一個(gè)協(xié)議卦溢『啵基于以前的示例,下面的示例擴(kuò)展了 Container
協(xié)議单寂,添加一個(gè) startsWith(_:)
方法贬芥。
extension Container where Item: Equatable {
func startsWith(_ item: Item) -> Bool {
return count >= 1 && self[0] == item
}
}
if [9, 9, 9].startsWith(42) {
print("Starts with 42.")
} else {
print("Starts with something else.")
}
// 打印 "Starts with something else."
上述示例中的泛型 where
子句要求 Item
符合協(xié)議,但也可以編寫(xiě)一個(gè)泛型 where
子句去要求 Item
為特定類型宣决。例如:
extension Container where Item == Double {
func average() -> Double {
var sum = 0.0
for index in 0..<count {
sum += self[index]
}
return sum / Double(count)
}
}
print([1260.0, 1200.0, 98.6, 37.0].average())
// 打印 "648.9"
具有泛型 where 子句的關(guān)聯(lián)類型
你可以在關(guān)聯(lián)類型后面加上具有泛型 where
的字句蘸劈。例如,建立一個(gè)包含迭代器(Iterator)的容器疲扎,就像是標(biāo)準(zhǔn)庫(kù)中使用的 Sequence
協(xié)議那樣昵时。你應(yīng)該這么寫(xiě):
protocol Container {
associatedtype Item
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }
associatedtype Iterator: IteratorProtocol where Iterator.Element == Item
func makeIterator() -> Iterator
}
迭代器(Iterator)的泛型 where
子句要求:無(wú)論迭代器是什么類型捷雕,迭代器中的元素類型,必須和容器項(xiàng)目的類型保持一致壹甥。makeIterator()
則提供了容器的迭代器的訪問(wèn)接口救巷。
一個(gè)協(xié)議繼承了另一個(gè)協(xié)議,你通過(guò)在協(xié)議聲明的時(shí)候句柠,包含泛型 where
子句浦译,來(lái)添加了一個(gè)約束到被繼承協(xié)議的關(guān)聯(lián)類型。例如溯职,下面的代碼聲明了一個(gè) ComparableContainer
協(xié)議精盅,它要求所有的 Item
必須是 Comparable
的。
protocol ComparableContainer: Container where Item: Comparable { }
泛型下標(biāo)
下標(biāo)能夠是泛型的谜酒,他們能夠包含泛型 where
子句叹俏。你可以把占位符類型的名稱寫(xiě)在 subscript
后面的尖括號(hào)里,在下標(biāo)代碼體開(kāi)始的標(biāo)志的花括號(hào)之前寫(xiě)下泛型 where
子句僻族。例如:
extension Container {
subscript<Indices: Sequence>(indices: Indices) -> [Item]
where Indices.Iterator.Element == Int {
var result = [Item]()
for index in indices {
result.append(self[index])
}
return result
}
}
這個(gè) Container
協(xié)議的擴(kuò)展添加了一個(gè)下標(biāo)方法粘驰,接收一個(gè)索引的集合,返回每一個(gè)索引所在的值的數(shù)組述么。這個(gè)泛型下標(biāo)的約束如下:
這個(gè) Container
協(xié)議的擴(kuò)展添加了一個(gè)下標(biāo):下標(biāo)是一個(gè)序列的索引蝌数,返回的則是索引所在的項(xiàng)目的值所構(gòu)成的數(shù)組。這個(gè)泛型下標(biāo)的約束如下:
- 在尖括號(hào)中的泛型參數(shù)
Indices
度秘,必須是符合標(biāo)準(zhǔn)庫(kù)中的Sequence
協(xié)議的類型顶伞。 - 下標(biāo)使用的單一的參數(shù),
indices
剑梳,必須是Indices
的實(shí)例唆貌。 - 泛型
where
子句要求 Sequence(Indices)的迭代器,其所有的元素都是Int
類型阻荒。這樣就能確保在序列(Sequence)中的索引和容器(Container)里面的索引類型是一致的挠锥。
綜合一下,這些約束意味著侨赡,傳入到 indices
下標(biāo)蓖租,是一個(gè)整型的序列。
(譯者:原來(lái)的 Container
協(xié)議羊壹,subscript
必須是 Int
型的蓖宦,擴(kuò)展中新的 subscript
,允許下標(biāo)是一個(gè)的序列油猫,而非單一的值稠茂。)