- 泛型函數(shù)
- 泛型類型
- 泛型擴(kuò)展
如下面的代碼:比較a, b兩個(gè)是否相等,a和b的數(shù)據(jù)類型不確定
思考: 能否用一個(gè)函數(shù),根據(jù)實(shí)際傳入的參數(shù)類型而進(jìn)行相應(yīng)類型的比較,即適用于多種類型的比較。泛型提供了這種可能性。
func isEqualsInt(a: Int, b: Int) -> Bool {
return (a == b)
}
func isEqualsDouble(a: Double, b: Double) ->Bool {
return (a == b)
}
func isEqualsString(a: String, b: String) -> Bool {
return (a == b)
}
泛型函數(shù)
func isEquals<T>(a: T, b: T) -> Bool {
return (a == b)
}
在函數(shù)名isEquals后面添加<T>,參數(shù)的類型也被聲明為T,T稱為占位符,函數(shù)在每次調(diào)用時(shí)傳入實(shí)際類型才能決定T所代表的類型。
注:如果有多種類型,可以使用其他大寫字母,一般情況下大家習(xí)慣于使用字母U,但也可以使用其他的字母。
使用泛型函數(shù)
func isEquals<T>(a: T, b: T) -> Bool的函數(shù)在編譯時(shí)會(huì)有錯(cuò)誤發(fā)生,這是因?yàn)椴⒉皇撬械念愋蚑都有“可比性”,T必須遵從Comparable協(xié)議的類型。Comparable協(xié)議表示"可比性",在Swift中基本數(shù)據(jù)類型以及字符串都是遵從Comparable協(xié)議的。
所以對(duì)泛型類型要有限制,這個(gè)限制就叫作泛型約束。
///泛型約束
func isEquals<T: Comparable>(a: T, b: T) -> Bool {
return (a == b)
}
let n1 = 200
let n2 = 100
print(isEquals(a: n1, b: n2))
let s1 = "ABC1"
let s2 = "ABC1"
print(isEquals(a: s1, b: s2))
多類型參數(shù)
多個(gè)占位符(多個(gè)占位符之間用逗號(hào),“,”分隔),示例如下:func isEquals<T, U>(a: T, b:U) -> Bool{...}
占位符不僅可以替代參數(shù)類型,還可以替代返回值類型,示例代碼如下:func isEquals<T>(a: T, b:T) -> T {...}
///泛型: 多類型參數(shù)
func isEquals<T, U>(a: T, b: U) -> T? {
return nil
}
func isEquals<T, U, K>(a: T, b: U) -> K? {
return nil
}
泛型類型
泛型不僅可以在函數(shù)中使用,而且可以應(yīng)用于類、結(jié)構(gòu)體和枚舉等類型定義,這些類型就是泛型類型。 泛型類型一般都是與集合有關(guān)的類型,如:數(shù)組、Set和字典等。
示例:
//===字符串隊(duì)列====
struct StringQueue {
var items = [String]()
mutating func queue(item: String) {
items.append(item)
}
mutating func dequeue() -> String? {
if items.isEmpty {
return nil
}else {
return items.remove(at: 0)
}
}
}
var strQueue = StringQueue()
//入隊(duì)
strQueue.queue(item: "張三")
strQueue.queue(item: "李四")
strQueue.queue(item: "王五")
strQueue.queue(item: "董六")
//出隊(duì)
print(strQueue.dequeue()!) //張三
print(strQueue.dequeue()!) //李四
print(strQueue.dequeue()!) //王五
print(strQueue.dequeue()!) //董六
print(strQueue.items)
改為使用泛型實(shí)現(xiàn)隊(duì)列,如下代碼
//泛型實(shí)現(xiàn)隊(duì)列
struct Queue<T> {
var items = [T]()
mutating func queue(item: T) {
items.append(item)
}
mutating func dequeue() -> T? {
if items.isEmpty {
return nil
}else {
return items.remove(at: 0)
}
}
}
var genericQueue = Queue<Int>()
genericQueue.queue(item: 3)
genericQueue.queue(item: 6)
genericQueue.queue(item: 9)
genericQueue.queue(item: 12)
print(genericQueue.dequeue()!)
print(genericQueue.dequeue()!)
print(genericQueue.dequeue()!)
print(genericQueue.dequeue()!)
var genericQueue2 = Queue<String>()
genericQueue2.queue(item: "a")
genericQueue2.queue(item: "b")
genericQueue2.queue(item: "c")
genericQueue2.queue(item: "d")
print(genericQueue2.dequeue()!)
print(genericQueue2.dequeue()!)
print(genericQueue2.dequeue()!)
print(genericQueue2.dequeue()!)
泛型擴(kuò)展
泛型類型可以支持?jǐn)U展,這種情況下定義的擴(kuò)展與其他普通擴(kuò)展沒(méi)有區(qū)別。
///泛型擴(kuò)展
struct Queue3<T> {
var items = [T]()
mutating func queue(item: T) {
items.append(item)
}
mutating func dequeue() -> T? {
if items.isEmpty {
return nil
}else {
return items.remove(at: 0)
}
}
}
//泛型擴(kuò)展: 對(duì)Queue3進(jìn)行擴(kuò)展
extension Queue3 {
func peek(position: Int) -> T? {
if position < 0 || position > items.count {
return nil
}else {
return items[position]
}
}
}
var genericDoubleQueue = Queue3<Double>()
genericDoubleQueue.queue(item: 1.34)
genericDoubleQueue.queue(item: 2.38)
genericDoubleQueue.queue(item: 3.46)
genericDoubleQueue.queue(item: 4.57)
print(genericDoubleQueue.peek(position: 2)!) //3.46