Swift 泛型


Swift 提供了泛型讓你寫出靈活且可重複使用的函數和類型。

Swift 標準函式庫是透過泛型程式碼建構出來的。

Swift 的陣列和字典類型都是泛型集合。

你可以建立一個Int數組,也可以建立一個String數組,甚至可以是任何其他 Swift 的類型資料數組。

以下實例是一個非泛型函數exchange 用來交換兩個Int 值:

// 定义一个交换两个变量的函数
func exchange(inout a: Int, inout b: Int) {
    let temp = a
    a = b
    b = temp
}

var numb1 = 100
var numb2 = 200

print("交换前数据: \(numb1) 和 \(numb2)")
exchange(&numb1, b: &numb2)
print("交换后数据: \(numb1) 和 \(numb2)")

以上程式執行輸出結果為:

交换前数据: 100 和 200
交换后数据: 200 和 100

泛型函數可以存取任何類型,如Int 或String。

以下實例是一個泛型函數exchange 用來交換兩個Int 和String 值:

func exchange<T>(inout a: T, inout b: T) {
    let temp = a
    a = b
    b = temp
}

var numb1 = 100
var numb2 = 200

print("交换前数据:  \(numb1) 和 \(numb2)")
exchange(&numb1, b: &numb2)
print("交换后数据: \(numb1) 和 \(numb2)")

var str1 = "A"
var str2 = "B"

print("交换前数据:  \(str1) 和 \(str2)")
exchange(&str1, b: &str2)
print("交换后数据: \(str1) 和 \(str2)")

以上程式執行輸出結果為:

交换前数据:  100 和 200
交换后数据: 200 和 100
交换前数据:  A 和 B
交换后数据: B 和 A

這個函數的泛型版本使用了佔位類型名字(通常此情況下用字母T來表示)來取代實際類型名稱(如Int、String或Double)。佔位類型名稱沒有提示T必須是什麼類型,但是它提示了a和b必須是同一型別T,而不管T表示什麼型別。只有 exchange(_:_:)函數在每次呼叫時所傳入的實際類型才能決定T所代表的類型。

另一個不同之處在於這個泛型函數名後面跟著的佔位型別名字(T)是用尖括號括起來的(


泛型型別

Swift 允許你定義你自己的泛型類型。執行輸出結果為:

struct TOS<T> {
    var items = [T]()
    mutating func push(item: T) {
        items.append(item)
    }
    
    mutating func pop() -> T {
        return items.removeLast()
    }
}

var tos = TOS<String>()
tos.push("Swift")
print(tos.items)

tos.push("泛型")
print(tos.items)

tos.push("类型参数")
print(tos.items)

tos.push("类型参数名")
print(tos.items)


let deletetos = tos.pop()

擴充泛型類型

當你擴充一個泛型類型的時候(使用extension 關鍵字),你並不需要在擴充功能的定義中提供類型參數清單。
#實例

下面的範例擴展了泛型TOS 類型,為其新增了一個名為first 的唯讀計算屬性,它將會傳回目前堆疊頂端的元素而不會將其從堆疊中移除。的型別參數,或遵循一個特定的協定或協定構成。參數鏈的一部分。結果為:

["Swift"]
["Swift", "泛型"]
["Swift", "泛型", "类型参数"]
["Swift", "泛型", "类型参数", "类型参数名"]

關聯類型實例

Swift 中使用typealias 關鍵字來設定關聯類型。多個關聯類型作為協定定義的一部分是非常有用的。類型符合泛型函數或類別的定義約束。

你可以在參數清單中透過where語句定義參數的限制。

你可以寫一個where語句,緊接在在類型參數列表後面,where語句後面跟著一個或多個針對關聯類型的約束,以及(或)一個或多個類型和關聯類型間的等價(equality)關係。

實例

下面的範例定義了一個名為allItemsMatch的泛型函數,用來檢查兩個Container實例是否包含相同順序的相同元素。

如果所有的元素能夠匹配,那麼傳回一個為true的Boolean值,反之則為false。

struct TOS<T> {
    var items = [T]()
    mutating func push(item: T) {
        items.append(item)
    }
    
    mutating func pop() -> T {
        return items.removeLast()
    }
}

var tos = TOS<String>()
tos.push("Swift")
print(tos.items)

tos.push("泛型")
    print(tos.items)
    
    tos.push("类型参数")
    print(tos.items)
    
    tos.push("类型参数名")
    print(tos.items)

// 扩展泛型 TOS 类型
extension TOS {
    var first: T? {
        return items.isEmpty ? nil : items[items.count - 1]
    }
}

if let first = tos.first {
    print("栈顶部项:\(first)")
}

以上程式執行輸出結果為:

["Swift"]
["Swift", "泛型"]
["Swift", "泛型", "类型参数"]
["Swift", "泛型", "类型参数", "类型参数名"]
栈顶部项:类型参数名