Swift --- 泛型(Generics)和关联类型(Associated Type)

    泛型可以将类型参数化,提高代码复用率,减少代码量
func swapValues<T>(_ a: inout T, _ b: inout T) {
          
   
        (a, b) = (b, a)
    }
    var n1 = 10
    var n2 = 20
    swapValue(&n1, &n2)
    泛型函数赋值给变量
var fn:(inout: Int, inout: Int) -> () = swapValues
fn(&n1, &n2)
var test<T1, T2>(_ t1: T1, _ t2: T2) {
          
   }
var fn: (Int, Double) -> () = test
    类泛型
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 stack = Stack<Int>()
class SubStack<E> : Stack<E> {
          
   }
    结构体泛型
struct Stack<E> {
          
   
    var elements = [E]()
    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)
let score2 = Score.point(99.5)
let score3 = Score<Int>.grade("A")   //必须初始化泛型类型

关联类型Associated Type

    关联类型的作用:给协议中用到的类型定义一个占位名称 协议中可以拥有多个关联类型
protocol Stackable {
          
   
    associatedtype Element //关联类型
    //associatedtype Element2 //关联类型
    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 }
 }

类型约束:

protocol Stackable {
          
   
    associatedtype : Equatable
}
class Stack<E: Equatable> : Stackable {
          
   
    typealias Element = E
}
func equal<S1: Stackable, S2: Stackable>(_ s1: S1, _ s2: S2) -> BOOl 
where S1.Element == S2.Element, S1.Element : Hashable {
          
   
    return false
}

协议类型的注意点:

    关联类型不能直接作为返回值
protocol Runnable {
          
   
    associatedtype Speed
    var speed: Speed {
          
    get }
}
class Person : Runnable {
          
   
    var speed: Double {
          
    0.0 }
}
class Car : Runnable {
          
   
    var speed: Int {
          
    0 }
   func run()  {
          
   }
}
解决方案1
func get<T: Runnable>(_ type: Int) -> T {
          
   
    if type == 0 {
          
   
        return Student() as! T
    }
    return Person() as! T
}
var r1 = get(0)
var r1 = get(1)
解决方案2 不透明类型,只能返回一种类型,屏蔽具体类型,只暴露协议类型
func get(_ type: Int) -> some Runable {
          
   
    //if type == 0 {
          
   
    //    return Student()
    //}
    return Person()
}
var r1 = get(0)
r1.speed   //Runable.Speed
//ri.run() 不能调用
    some除了用在返回值类型上,一般还可以用在属性类型上
protocol Runnable {
          
    associatedtype Speed }
class Dog : Runnable {
          
    typealias Speed = Double }
class Person {
          
   
    var pet: some Runnable {
          
   
        return Dog()
    }
}
    或者 下面这种也是一种看不到真实类型的方式
protocol Runnable {
          
     }
class Dog : Runnable {
          
    }
class Person {
          
   
    var pet: Runnable {
          
   
        return Dog()
    }
}
经验分享 程序员 微信小程序 职场和发展