23.泛型
2021-07-26 本文已影响0人
LucXion
泛型代码让你能根据自定义的需求,编写出适用于任意类型的、灵活可复用的函数及类型。你可避免编写重复的代码,而是用一种清晰抽象的方式来表达代码的意图。
函数、类型参数
func swapTwo_Int(_ a:inout Int,_ b: inout Int){
let temp = a
a = b
b = temp
}
func swapTwo_String(_ a:inout String,_ b: inout String){
let temp = a
a = b
b = temp
}
// <T>占位符类型
func swapTwo<T>( _ a:inout T, _ b:inout T){
let temp = a
a = b
b = temp
}
命名规范:大多情况下,类型参数具有描述下的名称,例如字典
Dictionary<Key, Value>
中的Key
和Value
及数组Array<Element>
中的Element
,这能告诉阅读代码的人这些参数类型与泛型类型或函数之间的关系。然而,当它们之间没有有意义的关系时,通常使用单个字符来表示,例如T
、U
、V
类型 + 扩展 + 类型约束
除了泛型函数,Swift 还允许自定义泛型类型。这些自定义类、结构体和枚举可以适用于任意类型,类似于
Array
和Dictionary
。
-
类型 + 泛型
struct Stack<Element>{ // <Element>占位符类型 var stack : [Element] = [] mutating func push(addIn element:Element) { stack.append(element) } mutating func pop() { stack.removeLast() } }
-
延展 + 泛型
extension Stack { var topItem:Element? { // 可以直接使用类定义处的泛型 return stack.isEmpty ? nil: stack.last } } var stackInt = Stack<Int>()// 定义泛型类型 stackInt.push(addIn: 111) stackInt.push(addIn: 9999) stackInt.pop() print(stackInt.topItem!)
-
类 + 泛型 + 类型约束
struct CompareInt { static func compare(num1:Int,num2:Int) -> Bool { return num1 == num2 } } struct CompareType<T:Equatable> { static func compare(num1:T,num2:T) -> Bool { return num1 == num2 } } print(CompareType.compare(num1: 1, num2: 1))
关联类型
关联类型通过 associatedtype
关键字来指定
-
协议 + 关联类型
protocol stack { associatedtype Item // associatedtype 关键字来声明关联类型 var list:[Item]{set get} func push(item:Item) func pop() } class Person:stack { typealias Item = Int // typealias 来指定关联类型,也可以省略,省略以后Swift会在第一次指定关联类型的地方确定所有关联类型 var list : [Item] = [] func push(item: Int) { list.append(item) } func pop() { list.removeLast() } }
-
扩展 + 关联类型
- 无法直接在扩展中实现,只有在类定义的时候有同名的实现,才能在扩展中声明该类遵循了该协议
-
给关联类型添加约束
protocol Container { associatedtype Item: Equatable }
-
关联类型约束里使用协议
protocol P1 { associatedtype Item func push(item:Item) } protocol P2:P1 { /* Suffix 必须遵循协议 P2 并且 它的 Item 类型必须是和容器里的 Item 类型相同 */ associatedtype Suffix:P2 where Suffix.Item == Item func response() -> Suffix } class Person:P2 { var list:[Int] = [] func push(item: Int) { list.append(item) } func response() -> Person { // Person中的Item = Int , 此处 Item = Int return self } }
泛型 where 语句
对关联类型添加约束通常是非常有用的。你可以通过定义一个泛型
where
子句来实现。通过泛型where
子句让关联类型遵从某个特定的协议,以及某个特定的类型参数和关联类型必须类型相同。
protocol Container {
associatedtype Item // Equatable 不能写在这里,否则 Array中找不到同名实现
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }
}
struct Stack:Container {
var list:[Item] = []
// Container 实现
typealias Item = Int
var count: Int {
return list.count
}
mutating func append(_ item: Item) {
list.append(item)
}
subscript(i: Int) -> Item {
return list[i]
}
}
extension Array:Container {} // 已经有了实现,可以在延展中声明遵循了协议
/// where 关键字写在 返回值后,多个条件用逗号隔开
func allItemsMatch<C1:Container,C2:Container>(parameter1:C1,parameter2:C2)->Bool where C1.Item == C2.Item,C1.Item:Equatable {
if parameter1.count != parameter2.count {
return false
}
for index in 0..<parameter1.count {
if parameter1[index] != parameter2[index] {
return false
}
}
return true
}
var c1 = Stack.init(list: [1,2,3,4,6])
var c2 = [1,2,3,4,5]
print(allItemsMatch(parameter1: c1, parameter2: c2))
具有泛型 where子句的 扩展
extension Stack where Element: Equatable { // 在延展后给泛型添加约束,只有满足条件才能调用延展中的方法
func isTop(_ item: Element) -> Bool {
guard let topItem = items.last else {
return false
}
return topItem == item
}
}
包含上下文关系的 where 分句
extension Container {
func average() -> Double where Item == Int { // 给某个指定函数添加泛型约束,只有满足条件才能使用这个方法
var sum = 0.0
for index in 0..<count {
sum += Double(self[index])
}
return sum / Double(count)
}
func endsWith(_ item: Item) -> Bool where Item: Equatable {
return count >= 1 && self[count-1] == item
}
}
泛型下标
extension Container {
subscript<Indices: Sequence>(indices: Indices) -> [Item]
where Indices.Iterator.Element == Int { // 定义泛型 + where 约束条件
var result: [Item] = []
for index in indices {
result.append(self[index])
}
return result
}
}