Swift(十二) 泛型

泛型

泛型函数

1
2
3
4
5
6
7
8
9
10
11
12
func swapTwoValues<T>(inout a: T, inout _ b: T) {
let temporaryA = a
a = b
b = temporaryA
}

var someInt = 3
var anotherInt = 7

swapTwoValues(&someInt,&anotherInt)

print("\(someInt) \(anotherInt)")

类型参数

<T> <Key> <Value> 驼峰式命名法

泛型类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct Stack<T> {
var items = [T]()

mutating func push(item: T) {
items.append(item)
}

mutating func pop() -> T {
return items.removeLast()
}
}


var stackOfStrings = Stack<String>()

stackOfStrings.push("a")
stackOfStrings.push("b")
stackOfStrings.push("c")

let popedString = stackOfStrings.pop()

扩展一个泛型类型

扩展一个泛型类型,不需要在扩展的定义中提供类型参数列表。原始类中声明的类型参数列表也可在扩展中使用

1
2
3
4
5
6
7
8

extension Stack {

var topItem: T? {

return items.isEmpty ? nil : items[items.count - 1]
}
}

类型约束

1
2
3
func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
// 这里是函数主体
}

类型约束实例

1
2
3
4
5
6
7
8
9
func findIndex<T: Equatable>(array: [T], _ valueToFind:T) -> Int? {

for (index, value) in array.enumerate() where value == valueToFind {

return index
}

return nil
}

关联类型

当定义一个协议时,有的时候声明一个或多个关联类型作为协议定义的一部分是非常有用的。一个关联类型作为协议的一部分,给定了类型的一个占位名(或别名)。作用于关联类型上实际类型在协议被实现前是不需要指定的。关联类型被指定为typealias关键字。

关联类型实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
protocol Container {
typealias ItemType
mutating func append(item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}

struct IntStack: Container {
// IntStack的原始实现
var items = [Int]()
mutating func push(item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}
// 遵循Container协议的实现
typealias ItemType = Int
mutating func append(item: Int) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> Int {
return items[i]
}
}

扩展一个存在的类型为一指定关联类型

1
extension Array : Container {}

Array本身已经实现了Container 的方法,所以只需通过扩展使Array遵循协议,即可将Array当做Container类型使用

Where

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func allItemsMatch<
C1: Container, C2: Container
where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
(someContainer: C1, anotherContainer: C2) -> Bool {

// 检查两个Container的元素个数是否相同
if someContainer.count != anotherContainer.count {
return false
}

// 检查两个Container相应位置的元素彼此是否相等
for i in 0..<someContainer.count {
if someContainer[i] != anotherContainer[i] {
return false
}
}

// 如果所有元素检查都相同则返回true
return true

}