swift 协议与函数派发的几点问题

1、

问题先从一个协议说起

protocol DefaultProtocol: NSObjectProtocol{
    func defaultImpl()
}
extension DefaultProtocol{
    func defaultImpl(){
        print("默认实现")
    }
}

这是一个方法带有默认实现的协议,实现它:

//1
class SuperClass: NSObject, DefaultProtocol{}
class SubClass: SuperClass {
    func defaultImpl() {
        print("子类实现")
    }
}

使用:

let object: DefaultProtocol = SubClass()
object.defaultImpl()

输出是什么呢?

可以简单分析一下代码:
object 指定为 DefaultProtocol 类型,其指针指向的是SubClass对象, 当调用object.defaultImpl() 时,系统首先拿到objectisa指针找到 SubClass 然后找到SubClass对应的虚函数表,根据偏移量找到defaultImpl()方法调用,输出 子类实现

大概就是这么个流程对吧

ok
现在来看输出

纳尼?!!不科学!
这太不唯物主义了!

难道swift实现了什么黑魔法?

我们把代码稍微调整一下:

//2
class SuperClass: NSObject, DefaultProtocol{
    func defaultImpl() {
        print("父类实现")
    }
}
class SubClass: SuperClass {
    override func defaultImpl() {
        print("子类实现")
    }
}

再来看输出:

ok, 这才是我们想要的结果。

由1、2结合可以推测出来,当SuperClass没有实现协议方法时,SubClass对协议方法的实现并不会写到自己的method_list中, 所以才会调用方法的默认实现,在 2中SuperClass实现了协议方法,SubClass重写覆盖了父类在method_list中的方法,才能正常调用。

通过google(这里)后发现这玩意很可能是个bug,并且尝试过Javakotlin的相同实现方法都没有问题。

那就暂且当作一个待修复的 bug 处理吧。

2、

那自己写的协议与系统提供的协议会不会有不一样的表现呢?

拿个我们最熟悉的协议 UIScrollViewDelegate举个简单的。

class SuperVC: UIViewController, UIScrollViewDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(scrollView)
    }
    lazy var scrollView: UIScrollView = {
        let o = UIScrollView.init(frame: self.view.bounds)
        o.contentSize = CGSize(width: ScreenW*2, height: ScreenH*2)
        o.backgroundColor = .magenta
        o.delegate = self
        return o }()
}

class SubVC: SuperVC {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        print("滚动\(scrollView.contentOffset)")
    }
}

输出

父类没有实现的协议方法在子类正常调用!!!
???????


如果问题到这里,就按照bug解决, 爱谁谁,以后多注意就完事了

但偏偏我又多做了一个试验

3、

如果实现协议的类带了泛型呢?

Let's coding happily

class SuperVC: UIViewController, UIScrollViewDelegate {

    var text: T?
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(scrollView)
    }
    lazy var scrollView: UIScrollView = {
        let o = UIScrollView.init(frame: self.view.bounds)
        o.contentSize = CGSize(width: ScreenW*2, height: ScreenH*2)
        o.backgroundColor = .magenta
        o.delegate = self
        return o }()
}

class SubVC: SuperVC {
    override var text: NSString? {get{return "范型~~~"} set{}}
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        print("滚动\(scrollView.contentOffset)")
        print(text!)
    }
}

输出:

并没有任何输出!

同问题1一样子类跳过父类实现的协议方法并没有被调用
而现在我只是多加了个泛型而已

试验到这我已经词穷了, 一万头草泥马,万脸懵逼。

问题

1、协议中的optional方法, 实现的时候是通过何种方式派发的?
2、为什么自己实现的协议与系统表现的不一样,系统提供的协议做了什么?
3、swift在编译的过程中,对有范型的类除了做了泛型擦除还做了什么,以至于影响到了函数的派发?

你可能感兴趣的:(swift 协议与函数派发的几点问题)