Swift
泛型
泛型的本質(zhì)是參數(shù)化類型,也就是說所有操作的數(shù)據(jù)類型被制定為一個參數(shù),這種參數(shù)類型可以用在類型、函數(shù)和方法中。
1.泛型函數(shù)
泛型可以用于函數(shù)的參數(shù)和返回值等,使用了泛型的函數(shù)通常稱為泛型函數(shù)。下面看3個普通函數(shù)
// 1.1關(guān)于Int類型的交換函數(shù)
func exchangeInt(a:inout Int,b:inout Int){
let temp = a
a = b
b = temp
}
var numb1 = 100
var numb2 = 200
print("交換前 numb1 = \(numb1) and numb2 = \(numb2)")
exchangeInt(a: &numb1, b: &numb2)
print("交換后 numb1 = \(numb1) and numb2 = \(numb2)")
// inout在寫法上與C語言傳遞地址的寫法十分類似,在調(diào)用函數(shù)傳入?yún)?shù)是帶有前綴&,就好像取地址傳進去了一樣,實則不然。
// 1.2關(guān)于Double類型的交換函數(shù)
func exchangeDouble(a:inout Double,b:inout Double){
let temp = a
a = b
b = temp
}
var numbA = 30.5
var numbB = 107.77
print("交換前 numb1 = \(numbA) and numb2 = \(numbB)")
exchangeDouble(a: &numbA, b: &numbB)
print("交換后 numb1 = \(numbA) and numb2 = \(numbB)")
// 1.3關(guān)于String類型的交換函數(shù)
func exchangeString(a:inout String,b:inout String){
let temp = a
a = b
b = temp
}
var strA = "Harry"
var strB = "Sun"
print("交換前 numb1 = \(strA) and numb2 = \(strB)")
exchangeString(a: &strA, b: &strB)
print("交換后 numb1 = \(strA) and numb2 = \(strB)")
inout在寫法上與C語言傳遞地址的寫法十分類似,在調(diào)用函數(shù)傳入?yún)?shù)是帶有前綴&,就好像取地址傳進去了一樣,實則不然。
上 面這三個函數(shù)實現(xiàn)都是相同的,唯一不同的是傳入的參數(shù)類型不同,這樣顯得代碼比較冗余,所以我們使用泛型函數(shù)
func exchange<T>(a:inout T,b:inout T){
let temp = a
a = b
b = temp
}
// 這樣對于任何類型都是可以的
numb1 = 100
numb2 = 200
print("交換之前 numb1 = \(numb1) and numb2 = \(numb2)")
exchange(a: &numb1,b: &numb2)
print("交換之后 numb1 = \(numb1) and numb2 = \(numb2)")
numbA = 30.5
numbB = 107.77
print("交換之前 numb1 = \(numbA) and numb2 = \(numbB)")
exchange(a: &numbA,b: &numbB)
print("交換之后 numb1 = \(numbA) and numb2 = \(numbB)")
strA = "Harry"
strB = "Sun"
print("交換之前 numb1 = \(strA) and numb2 = \(strB)")
exchange(a: &strA,b: &strB)
print("交換之后 numb1 = \(strA) and numb2 = \(strB)")
2.泛型類型
swift不但允許定義泛型函數(shù),而且還允許定義泛型類型。這些自定義泛型類型可以是類、結(jié)構(gòu)體和枚舉,能適用于任何類型,如同A仍然有何Dictionary的用法一樣
// 先定義一個普通類型的棧
struct IntStack {
var items = [Int]()
mutating func push(item:Int){
items.append(item)
}
mutating func po() -> Int{
return items.removeLast()
}
}
// 再定義一個泛型類型的棧,從泛型的棧中可以看出泛型類型
struct Stack<Element> {
var items = [Element]()
mutating func push(item:Element){
items.append(item)
}
mutating func pop() -> Element{
return items.removeLast()
}
}
var stackOfStrings = Stack<String>()
stackOfStrings.push(item: "A")
stackOfStrings.push(item: "B")
stackOfStrings.push(item: "C")
stackOfStrings.push(item: "D")
let fromTheTop = stackOfStrings.pop()
print("fromTheTop的值是\(fromTheTop)")
// 擴展泛型棧
extension Stack{
var topItem:Element?{
return items.isEmpty ? nil : items[items.count - 1]
}
}
if let topItem = stackOfStrings.topItem{
print("棧頂?shù)脑厥荺(topItem)")
}
3.類型約束
默認情況下,泛型函數(shù)和泛型類型可作用于任何類型,不過,有時候需要對泛型函數(shù)和泛型類型中的類型做一些強制約束,例如,swift的Dictionary類型對字典的鍵類型做出約束,要求鍵類型是可哈希的,下面舉一個例子更好的理解類型約束
func findStringIndex(array:[String],valueToFind:String) -> Int?{
for(index,value) in array.enumerated(){
if value == valueToFind {
return index
}
}
return nil
}
let strings = ["Beijing","Shanghai","Guangzhou","Shangdong","Zhengzhou"]
if let foundIndex = findStringIndex(array: strings, valueToFind: "Shanghai"){
print("Shanghai在數(shù)組中的位置是\(foundIndex)")
}
// findStringIndex這個函數(shù)只能查找字符串在數(shù)組中的索引,用處不是很大,下面寫出相同功能的泛型函數(shù)findIndex(_,_)用占位類型T替換String
func findIndex<T:Equatable>(array:[T],valueToFind:T) -> Int? {
for (index,Value) in array.enumerated() {
if(Value == valueToFind){
return index
}
}
return nil
}
// 這里我們使用了Equatable協(xié)議作為限定,在swift標準庫中定義了一個Equatable協(xié)議,該協(xié)議要求其遵守者必須實現(xiàn)等式符(==),從而能使用==對符合該協(xié)議的類型值進行比較,因為很多類型和自定義的類型都沒有遵守該協(xié)議
let doubleIndex = findIndex(array:[3.14159,0.1,0.25], valueToFind: 9.3)
print("9.3在數(shù)組中的位置是\(String(describing: doubleIndex))")
let stringIndex = findIndex(array: ["ios","android","h5"], valueToFind: "ios")
print("ios在數(shù)組中的位置是\(String(describing: stringIndex))")