泛型
泛型概念
泛型代表某种指定的类型
泛型是 Swift 中最强大的特性之一,大量的 Swift 标准库使用了泛型,比如数组和字典都是泛型集合。
泛型能让你写出支持任意类型的灵活的、可复用的函数,它能将类型参数化,提高代码复用率,减少代码量。
泛型定义
- 泛型可以定义在函数、类、结构体、枚举后
- 泛型名称以逗号分隔,并用尖括号包裹起来
- 泛型可以在当前作用域内或扩展中使用
泛型示例
泛型在函数中使用时,可以自动推断类型
func swap<T>(_ a: inout T, _ b: inout T) {
(a, b) = (b, a)
}
var x = 10, y = 20
print(x, y) // 10 20
swap(&x, &y)
print(x, y) // 20 10
泛型在类、结构体、枚举中使用时,需要在实例初始化时就指定好类型
struct Stack<Element> {
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
func description() {
print(items)
}
}
var stack1 = Stack<String>()
stack1.push("apple")
stack1.push("orange")
stack1.description()
var stack2 = Stack<Int>()
stack2.push(1)
stack2.push(2)
stack2.description()
关联类型
- 关联类型与泛型的用途、用法类似
- 关联类型只能用于协议,而泛型不能在协议中使用
- 当某个类型遵守协议时,也需要给协议的关联类型指定实际类型
protocol CollectionProtocol {
associatedtype ItemType
var count: Int { get }
subscript(i: Int) -> ItemType { get }
mutating func append(_ item: ItemType)
}
struct Stack<Element>: CollectionProtocol {
/**
Generics / `String` / `Int` ...
*/
typealias ItemType = Element
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
// MARK: - ContainerProtocol
var count: Int {
return items.count
}
subscript(i: Int) -> Element {
return items[i]
}
mutating func append(_ item: Element) {
self.push(item)
}
}
类型约束
类型约束是指类型必须继承自特定的类或遵循特定的协议。举例:
func test<T: Equatable & Comparable>(a: T, b: T) -> Bool {
return false
}
func index<T: Equatable>(of valueToFind: T, in array:[T]) -> Int? {
for (index, value) in array.enumerated() {
if value == valueToFind {
return index
}
}
return nil
}
extension Array where Element: Equatable {
func index(of valueToFind: Element) -> Int? {
for (index, value) in self.enumerated() {
if value == valueToFind {
return index
}
}
return nil
}
}
条件约束
where 语句可以对类型进行约束、对类型之间的等价关系进行约束,以及其他条件约束。
protocol CollectionProtocol {
associatedtype ItemType
// associatedtype ItemType: Equatable
var count: Int { get }
subscript(i: Int) -> ItemType { get }
mutating func append(_ item: ItemType)
}
struct Stack<Element>: CollectionProtocol {
/**
Generics / `String` / `Int` ...
*/
typealias ItemType = Element
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
// MARK: - ContainerProtocol
var count: Int {
return items.count
}
subscript(i: Int) -> Element {
return items[i]
}
mutating func append(_ item: Element) {
self.push(item)
}
}
extension Array: CollectionProtocol{}
func allItemsMatch<C1: CollectionProtocol, C2: CollectionProtocol>
(_ collection1: C1, _ collection2: C2) -> Bool
where C1.ItemType == C2.ItemType, C1.ItemType: Equatable
{
if collection1.count != collection2.count {
return false
}
for i in 0..<collection1.count {
if collection1[i] != collection2[i] {
return false
}
}
return true
}
var tos = Stack<String>()
tos.push("google")
tos.push("runoob")
tos.push("taobao")
var aos = ["google", "runoob", "taobao"]
if allItemsMatch(tos, aos) {
print("匹配所有元素")
} else {
print("元素不匹配")
}
[备注]:参考