• Swift中的泛型(Generics)


     

    泛型(Generics)

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

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

    1. class Stack<E> {
    2. var elements = [E]()
    3. func push(_ element: E) -> Void {
    4. elements.append(element)
    5. }
    6. func pop() -> E {
    7. elements.removeLast()
    8. }
    9. func top() -> E {
    10. elements.last!
    11. }
    12. func size() -> Int {
    13. elements.count
    14. }
    15. }
    16. var intStack = Stack<Int>()
    17. var stringStack = Stack<String>()
    18. var anyStack = Stack<Any>()
    1. class SubStack<E>: Stack<E> {
    2. }
    3. struct Stack<E> {
    4. var elements = [E]()
    5. mutating func push(_ element: E) {
    6. elements.append(element)
    7. }
    8. mutating func pop() -> E {
    9. elements.removeLast()
    10. }
    11. func top() -> E {
    12. elements.last!
    13. }
    14. func size() -> Int {
    15. elements.count
    16. }
    17. }

    汇编分析泛型的实现原理

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

    关联类型(Associated Type)

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

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

    1. protocol Stackable {
    2. associatedtype Element
    3. mutating func push(_ element: Element)
    4. mutating func pop() -> Element
    5. func top() -> Element
    6. func size() -> Int
    7. }
    1. class StringStack: Stackable {
    2. // typealias Element = String 可写可不写
    3. var elements = [String]()
    4. func push(_ element: String) -> Void {
    5. elements.append(element)
    6. }
    7. func pop() -> String {
    8. elements.removeLast()
    9. }
    10. func top() -> String {
    11. elements.last!
    12. }
    13. func size() -> Int {
    14. elements.count
    15. }
    16. }

    类型约束

    1. protocol Runnable {}
    2. class Person {}
    3. func swapValues<T: Person & Runnable>(_ a: inout T, _ b: inout T) -> Void {
    4. (a, b) = (b, a)
    5. }

    更多的约束

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

    协议类型的注意点

    1. protocol Runnable {}
    2. class Person: Runnable {}
    3. class Car: Runnable {}
    4. func getObject(_ type: Int) -> Runnable {
    5. if type == 0 {
    6. return Person()
    7. }
    8. return Car()
    9. }
    10. var r1 = getObject(0)
    11. var r2 = getObject(1)

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

    1. protocol Runnable {
    2. associatedtype Speed
    3. var speed: Speed {
    4. get
    5. }
    6. }
    7. class Person: Runnable {
    8. var speed: Double {
    9. 0.0
    10. }
    11. }
    12. class Car: Runnable {
    13. var speed: Int {
    14. 0
    15. }
    16. }
    17. func getObject(_ type: Int) -> Runnable {
    18. if type == 0 {
    19. return Person()
    20. }
    21. return Car()
    22. }

    泛型解决

    解决方案1:使用泛型

    1. protocol Runnable {
    2. associatedtype Speed
    3. var speed: Speed {
    4. get
    5. }
    6. }
    7. class Person: Runnable {
    8. var speed: Double {
    9. 0.0
    10. }
    11. }
    12. class Car: Runnable {
    13. var speed: Int {
    14. 0
    15. }
    16. }
    17. func getObject<T: Runnable>(_ type: Int) -> T {
    18. if type == 0 {
    19. return Person() as! T
    20. }
    21. return Car() as! T
    22. }
    23. var r1: Person = getObject(0)
    24. var r2: Car = getObject(1)

    不透明类型(Opaque Type)

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

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

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

    some

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

    1. protocol Runnable {
    2. associatedtype Speed
    3. }
    4. class Dog: Runnable {
    5. typealias Speed = Double
    6. }
    7. class Person {
    8. var pet: some Runnable {
    9. return Dog()
    10. }
    11. }

  • 相关阅读:
    2022年0903我的SpringBoot框架入门的第一个程序
    『现学现忘』Git后悔药 — 30、版本回退git reset --hard命令说明
    SpringBoot中的日志使用
    70. 爬楼梯 --力扣 --JAVA
    Hdu2022 多校训练(5) BBQ
    MySQL学习——从命令行调用MySQL 程序
    Nodejs 使用 ZooKeeper 做服务发现
    华为程序员熬夜整合SpringCloud 源码之负载均衡 Ribbon,2W字带你深度分析
    getBoundingClientRect属性研究
    C++基础
  • 原文地址:https://blog.csdn.net/run_in_road/article/details/126247241