swapTwoValues函數(shù)和Stack類型可以作用于任何類型,不過,有的時候?qū)κ褂迷诜盒秃瘮?shù)和泛型類型上的類型強制約束為某種特定類型是非常有用的。類型約束指定了一個必須繼承自指定類的類型參數(shù),或者遵循一個特定的協(xié)議或協(xié)議構(gòu)成。
例如,Swift 的Dictionary類型對作用于其鍵的類型做了些限制。在字典的描述中,字典的鍵類型必須是可哈希,也就是說,必須有一種方法可以使其被唯一的表示。Dictionary之所以需要其鍵是可哈希是為了以便于其檢查其是否已經(jīng)包含某個特定鍵的值。如無此需求,Dictionary既不會告訴是否插入或者替換了某個特定鍵的值,也不能查找到已經(jīng)存儲在字典里面的給定鍵值。
這個需求強制加上一個類型約束作用于Dictionary的鍵上,當(dāng)然其鍵類型必須遵循Hashable協(xié)議(Swift 標(biāo)準(zhǔn)庫中定義的一個特定協(xié)議)。所有的 Swift 基本類型(如String,Int, Double和 Bool)默認(rèn)都是可哈希。
當(dāng)你創(chuàng)建自定義泛型類型時,你可以定義你自己的類型約束,當(dāng)然,這些約束要支持泛型編程的強力特征中的多數(shù)。抽象概念如可哈希具有的類型特征是根據(jù)它們概念特征來界定的,而不是它們的直接類型特征。
你可以寫一個在一個類型參數(shù)名后面的類型約束,通過冒號分割,來作為類型參數(shù)鏈的一部分。這種作用于泛型函數(shù)的類型約束的基礎(chǔ)語法如下所示(和泛型類型的語法相同):
func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
// function body goes here
}
上面這個假定函數(shù)有兩個類型參數(shù)。第一個類型參數(shù)T,有一個需要T必須是SomeClass子類的類型約束;第二個類型參數(shù)U,有一個需要U必須遵循SomeProtocol協(xié)議的類型約束。
這里有個名為findStringIndex的非泛型函數(shù),該函數(shù)功能是去查找包含一給定String值的數(shù)組。若查找到匹配的字符串,findStringIndex函數(shù)返回該字符串在數(shù)組中的索引值(Int),反之則返回nil:
func findStringIndex(array: String[], valueToFind: String) -> Int? {
for (index, value) in enumerate(array) {
if value == valueToFind {
return index
}
}
return nil
}
findStringIndex函數(shù)可以作用于查找一字符串?dāng)?shù)組中的某個字符串:
let strings = ["cat", "dog", "llama", "parakeet", "terrapin"]
if let foundIndex = findStringIndex(strings, "llama") {
println("The index of llama is \(foundIndex)")
}
// 輸出 "The index of llama is 2"
如果只是針對字符串而言查找在數(shù)組中的某個值的索引,用處不是很大,不過,你可以寫出相同功能的泛型函數(shù)findIndex,用某個類型T值替換掉提到的字符串。
這里展示如何寫一個你或許期望的findStringIndex的泛型版本findIndex。請注意這個函數(shù)仍然返回Int,是不是有點迷惑呢,而不是泛型類型?那是因為函數(shù)返回的是一個可選的索引數(shù),而不是從數(shù)組中得到的一個可選值。需要提醒的是,這個函數(shù)不會編譯,原因在例子后面會說明:
func findIndex<T>(array: T[], valueToFind: T) -> Int? {
for (index, value) in enumerate(array) {
if value == valueToFind {
return index
}
}
return nil
}
上面所寫的函數(shù)不會編譯。這個問題的位置在等式的檢查上,“if value == valueToFind”。不是所有的 Swift 中的類型都可以用等式符(==)進行比較。例如,如果你創(chuàng)建一個你自己的類或結(jié)構(gòu)體來表示一個復(fù)雜的數(shù)據(jù)模型,那么 Swift 沒法猜到對于這個類或結(jié)構(gòu)體而言“等于”的意思。正因如此,這部分代碼不能可能保證工作于每個可能的類型T,當(dāng)你試圖編譯這部分代碼時估計會出現(xiàn)相應(yīng)的錯誤。
不過,所有的這些并不會讓我們無從下手。Swift 標(biāo)準(zhǔn)庫中定義了一個Equatable協(xié)議,該協(xié)議要求任何遵循的類型實現(xiàn)等式符(==)和不等符(!=)對任何兩個該類型進行比較。所有的 Swift 標(biāo)準(zhǔn)類型自動支持Equatable協(xié)議。
任何Equatable類型都可以安全的使用在findIndex函數(shù)中,因為其保證支持等式操作。為了說明這個事實,當(dāng)你定義一個函數(shù)時,你可以寫一個Equatable類型約束作為類型參數(shù)定義的一部分:
func findIndex<T: Equatable>(array: T[], valueToFind: T) -> Int? {
for (index, value) in enumerate(array) {
if value == valueToFind {
return index
}
}
return nil
}
上一篇:Swift數(shù)組下一篇:Swift循環(huán)