final、dynamic、objc和_dynamicReplacement - ShenYj/ShenYj.github.io GitHub Wiki

final、dynamic、objc和_dynamicReplacement

  • static

    static 修饰后,类型方法采用静态调度

  • final

    • final修饰符只能修饰类,不能修饰结构体和枚举,表明该类不能被其他类继承,也就是它没资格当父类
    • final修饰符也可以修饰类中的属性、方法和下标,但前提是该类并没有被final修饰过
    • final修饰方法后,将原有的sil-vtable函数表调度变为静态调用(直接调用)
  • @objc

    标记暴露给Object-C, 不会修改方法的调度方式, 仍表调度 (前提是在类主体中,若在extension中会改为消息调度)

    • 对编译器来说被修饰的方法会生成两个方法, 一个默认存在Swift类的方法表中, 另一个暴露给Object-C使用

      • Object-C调用方法时, 会再调用swift定义的原有的方法
    • @objc修饰后, 就可以通过runtime API获取对应的信息了, 如方法列表, 但如果需要给Object-C使用, 还需要继承自NSObject,两个条件缺一不可

  • dynamic

    dynamic修饰的方法有了动态特性, 依旧是表调度

    允许被交换调用(@_dynamicReplacement(for: 方法名)), 类似于Object-C的运行时方法动态交换

  • @objc dynamic

    @objc dynamic 同时修饰后, 会变成消息调度

  • @_dynamicReplacement

    Swift 5 Method Swizzling@_dynamicReplacement(for: 方法) 修饰方法, 参数for:后面就是将被替换的方法
    即调用方法时会调用被@_dynamicReplacement(for: 方法)修饰的方法

    注: @_dynamicReplacement关键字需要使用在extension

    e.g. @_dynamicReplacement

    class Person {
    
        dynamic func speechChinese() {
            print("speechChinese")
        }
    }
    
    extension Person {
        @_dynamicReplacement(for: speechChinese())
        func speechEnglish() {
            print("speechEnglish")
        }
    }
    
    let p = Person()
    p.speechChinese() // 此时会调用 speechEnglish()

    参考链接

    Swift Native method swizzling

⚠️ **GitHub.com Fallback** ⚠️