final、dynamic、objc和_dynamicReplacement
优质
小牛编辑
130浏览
2023-12-01
final、dynamic、objc和_dynamicReplacement
结构体的方法是静态调用(直接调用), 方法默认不加任何修饰是通过
sil-vtable
函数表来进行调度
Object-C
的分类方法会插入到类的方法表中, 而Swift
的extension
方法是静态调用(免去了Object-C
插入扩展方法的异步操作, 理解为空间换取时间)
Swift
继承, 子类会复制一份父类的方法到自己的方法表中,然后再编译自身的方法至方法表
final
final
修饰符只能修饰类,表明该类不能被其他类继承,也就是它没资格当父类final
修饰符也可以修饰类中的属性、方法和下标,但前提是该类并没有被final
修饰过final
不能修饰结构体和枚举
@objc
标记暴露给
Object-C
, 不会修改方法的调度方式, 仍为直接/静态调用对编译器来说被修饰的方法会生成两个方法, 一个默认存在
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()