Swift 方法重写 原理

Swift 方法重写 报错 Overriding non-@objc declarations from extensions is not supported。
class Base {
    func show1() {   
    }
}

extension Base {
    func show2() { 
    }
}

class AA: Base {
    override func show2() {   
    }
}

extension AA {
    override func show1() {
    }
}

复制代码

当AA类的extension 重写 父类 Base 中的 show1 方法 或者 AA类在主体重写父类extension中的show2方法的时候, 编译器会提示错误 Overriding non-@objc declarations from extensions is not supported。swift

正确写法数组

class Base {
    @objc dynamic func show1() {
        
    }
}

extension Base {
    @objc func show2() {
        
    }
}

class AA: Base {
    
    override func show2() {
        
    }
    
}

extension AA {
    override func show1() {
        
    }
}

复制代码

若是主体方法加上 @objc dynamic 子类的extension 就能够重写了。缓存

父类的extension中的方法加 @objc 子类的主体就能够重写了。markdown

这个是为何那?

Swift 目前方法调度 分为三种调度 直接调度,表调度,消息调度ide

直接调度

直接调用方法声明 速度最快。可是不能动态的支持子类函数

表调度

通常用函数地址的数组来储存类中方法的声明spa

子类中Vtable 会添加父类的方法声明。code

消息调度

OC 语言 就是采用这种方法调度的。经过msg_send() 方法来从类中或者父类中查询方法。这个调度比较慢,可是有缓存机制。能够提高效率。具备很好的灵活性。orm

Swift对应调度表对象

对象 Static VTable Witness Table Message
Swift struct 默认行为 N/A : protocol N/A
Swift Class final extension 默认行为 : protocol dynamic
继承NSObject final extension 默认行为 : protocol dynamic
Protocol extension 默认行为 N/A : NSObjectProtocol @objc

extension 中的方法默认是直接调度。

经过方法调度方式能够知道。

直接调度是不能被继承的。

表调度只能被子类主体继承。

那么若是要实现开头的方法重写 只有让方法是消息调度。

经过 在主体方法 加 @objc dynamic 关键字 和 extension 方法中添加 @objc,来改变方法的调度为消息调度。

相关文章
相关标签/搜索