一.经典示例,泛型函数
// 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)
断点,查看汇编代码,发现函数调用是同一个地址