美文网首页读书
Swift中的泛型(Generics)

Swift中的泛型(Generics)

作者: 扑腾的蛾子 | 来源:发表于2022-08-19 10:20 被阅读0次

    泛型(Generics)

    1、泛型可以将类型参数化,提高代码复用率,减少代码量

    func swapValue<T>(_ a: inout T, _ b: inout T) -> Void {
        (a, b) = (b, a)
    }
    var fn: (inout Int, inout Int) -> () = swapValue
    

    class Stack<E> {
        var elements = [E]()
        func push(_ element: E) -> Void {
            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>()
    var anyStack = Stack<Any>()
    
    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
        }
    }
    

    汇编分析泛型的实现原理


    通过汇编我们可以看到两次调用的swapValues方法的地址是相同的,也就是说是相同的方法,汇编中有关于metadata的信息,所以推测Swift中的泛型是通过对元数据的处理实现的。

    关联类型(Associated Type)

    1、关联类型的作用:给协议中用到的类型定义一个占位名称

    2、协议中可以拥有多个关联类型

    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) -> Void {
            elements.append(element)
        }
        
        func pop() -> String {
            elements.removeLast()
        }
        
        func top() -> String {
            elements.last!
        }
        
        func size() -> Int {
            elements.count
        }
    }
    

    类型约束

    protocol Runnable {}
     
    class Person {}
     
    func swapValues<T: Person & Runnable>(_ a: inout T, _ b: inout T) -> Void {
        (a, b) = (b, a)
    }
    

    更多的约束

    func equal<S1: Stackable, S2: Stackable>(_ s1: S1, _ s2: S2) -> Bool
    where S1.Element == S2.Element, S1.Element: Hashable
    {
        return false
    }
    

    协议类型的注意点

    protocol Runnable {}
     
    class Person: Runnable {}
     
    class Car: Runnable {}
     
    func getObject(_ type: Int) -> Runnable {
        if type == 0 {
            return Person()
        }
        return Car()
    }
     
    var r1 = getObject(0)
    var r2 = getObject(1)
    

    1、如果协议中有associatedtype,那么会有类型识别不了的问题,以下代码会报错

    protocol Runnable {
        associatedtype Speed
        var speed: Speed {
            get
        }
    }
     
    class Person: Runnable {
        var speed: Double {
            0.0
        }
    }
     
    class Car: Runnable {
        var speed: Int {
            0
        }
    }
     
    func getObject(_ type: Int) -> Runnable {
        if type == 0 {
            return Person()
        }
        return Car()
    }
    

    泛型解决

    解决方案1:使用泛型

    protocol Runnable {
        associatedtype Speed
        var speed: Speed {
            get
        }
    }
     
    class Person: Runnable {
        var speed: Double {
            0.0
        }
    }
     
    class Car: Runnable {
        var speed: Int {
            0
        }
    }
     
    func getObject<T: Runnable>(_ type: Int) -> T {
        if type == 0 {
            return Person() as! T
        }
        return Car() as! T
    }
     
    var r1: Person = getObject(0)
    var r2: Car = getObject(1)
    

    不透明类型(Opaque Type)

    1、解决方案2:使用some关键字声明一个不透明类型

    func getObject(_ type: Int) -> some Runnable {
        return Car()
    }
    

    2、some限制只能返回一种类型

    some

    1、some除了用在返回值类型上,一般还可以用在属性类型上

    protocol Runnable {
        associatedtype Speed
    }
     
    class Dog: Runnable {
        typealias Speed = Double
    }
     
    class Person {
        var pet: some Runnable {
            return Dog()
        }
    }
    

    相关文章

      网友评论

        本文标题:Swift中的泛型(Generics)

        本文链接:https://www.haomeiwen.com/subject/adzygrtx.html