一.经典示例,泛型函数

// T代表类型,也可以是其他字符T1, T2, E等等
func swapValue<T>(_ a: inout T, _ b: inout T) {
    (a, b) = (b, a)
}

var n1 = 10
var n2 = 20
swapValue(&n1, &n2)

二.泛型类

class Stack<E> {

    var elements = [E]()
    
    func push(_ element: E) {
        elements.append(element)
    }
    func pop() -> E {
        elements.removeLast()
    }
    func top() -> E {
        elements.last!
    }
    func size() -> Int {
        elements.count
    }
}

// 如果使用这个泛型类,需要告诉它你是什么类型
var intStack = Stack<Int>()
var stringStack = Stack<String>()

// 如果定义了初始化方法,那么必须要使用初始化方法获取这个对象
// 这个时候就可以不使用<>来指定类型,因为参数firstElement已经指定了类型
// 当然为了更清晰的表达语义,最好加上<>
var intStack = Stack.init(firstElement: 11)

三.泛型结构体

struct Stack<E> {

    var elements = [E]()
    
    // mutating不加,编译器会报错
    mutating func push(_ element: E) {
        elements.append(element)
    }
    mutating func pop() -> E {
        elements.removeLast()
    }
    func top() -> E {
        elements.last!
    }
    func size() -> Int {
        elements.count
    }
}

四.泛型枚举

enum Score<T> {
    case point(T)
    case grade(String)
}

let score0 = Score<Int>.point(100)
let score1 = Score.point(99.5)
let score1 = Score<Int>.grade("A")

五.协议实现泛型,不能用<>,而是使用associatedtype关联类型

protocol Stackable {

    associatedtype Element // 关联类型
    mutating func push(_ element: Element)
    mutating func pop() -> Element
    func top() -> Element
    func size() -> Int
}

遵守协议

class StringStack: Stackable {
    
    // 给关联类型设定真实类型, 可省略,编译器会自己判断出类型
    // typealias Element = String
    var elements = [String]()
    
    func push(_ element: String) {
        elements.append(element)
    }
    func pop() -> String {
        elements.removeLast()
    }
    func top() -> String {
        elements.last!
    }
    func size() -> Int {
        elements.count
    }
}

当然也可以写一个泛型类

class StringStack<E>: Stackable {
    
    // 给关联类型设定真实类型, 可省略,编译器会自己判断出类型
    // typealias Element = String
    var elements = [E]()
    
    func push(_ element: E) {
        elements.append(element)
    }
    func pop() -> E {
        elements.removeLast()
    }
    func top() -> E {
        elements.last!
    }
    func size() -> Int {
        elements.count
    }
}

1.泛型函数的猜想: 编译器根据代码自动生成了不同类型的函数,因为C++中,泛型就是这么干的

func swapValue<T>(_ a: inout T, _ b: inout T) {
    (a, b) = (b, a)
}
// 编译器自动生成以下两个函数吗?????
func swapValue(_ a: inout Int, _ b: inout Int) {
    (a, b) = (b, a)
}

func swapValue(_ a: inout Double, _ b: inout Double) {
    (a, b) = (b, a)
}

var n1: Int = 10
var n2: Int = 20
swapValue(&n1, &n2)

var d1: Double = 10
var d2: Double = 20
swapValue(&d1, &d2)

断点,查看汇编代码,发现函数调用是同一个地址 demo