1、
問題先從一個協(xié)議說起
protocol DefaultProtocol: NSObjectProtocol{
func defaultImpl()
}
extension DefaultProtocol{
func defaultImpl(){
print("默認實現(xiàn)")
}
}
這是一個方法帶有默認實現(xiàn)的協(xié)議何吝,實現(xiàn)它:
//1
class SuperClass: NSObject, DefaultProtocol{}
class SubClass: SuperClass {
func defaultImpl() {
print("子類實現(xiàn)")
}
}
使用:
let object: DefaultProtocol = SubClass()
object.defaultImpl()
輸出是什么呢溉委?
可以簡單分析一下代碼:
object
指定為 DefaultProtocol
類型,其指針指向的是SubClass
對象爱榕, 當調(diào)用object.defaultImpl()
時瓣喊,系統(tǒng)首先拿到object
的 isa
指針找到 SubClass
然后找到SubClass
對應的虛函數(shù)表,根據(jù)偏移量找到defaultImpl()
方法調(diào)用黔酥,輸出 子類實現(xiàn)
大概就是這么個流程對吧
ok
現(xiàn)在來看輸出
納尼藻三?!跪者!不科學棵帽!
這太不唯物主義了!
難道swift實現(xiàn)了什么黑魔法渣玲?
我們把代碼稍微調(diào)整一下:
//2
class SuperClass: NSObject, DefaultProtocol{
func defaultImpl() {
print("父類實現(xiàn)")
}
}
class SubClass: SuperClass {
override func defaultImpl() {
print("子類實現(xiàn)")
}
}
再來看輸出:
ok逗概, 這才是我們想要的結(jié)果。
由1柜蜈、2結(jié)合可以推測出來仗谆,當
SuperClass
沒有實現(xiàn)協(xié)議方法時,SubClass
對協(xié)議方法的實現(xiàn)并不會寫到自己的method_list
中, 所以才會調(diào)用方法的默認實現(xiàn)淑履,在 2中SuperClass
實現(xiàn)了協(xié)議方法隶垮,SubClass
重寫覆蓋了父類在method_list
中的方法,才能正常調(diào)用秘噪。
通過google(這里)后發(fā)現(xiàn)這玩意很可能是個bug狸吞,并且嘗試過Java
和kotlin
的相同實現(xiàn)方法都沒有問題。
那就暫且當作一個待修復的 bug 處理吧指煎。
2蹋偏、
那自己寫的協(xié)議與系統(tǒng)提供的協(xié)議會不會有不一樣的表現(xiàn)呢?
拿個我們最熟悉的協(xié)議 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)")
}
}
輸出
父類沒有實現(xiàn)的協(xié)議方法在子類正常調(diào)用M肌!像街!
黎棠?晋渺??脓斩?木西??随静?
如果問題到這里八千,就按照bug解決, 愛誰誰燎猛,以后多注意就完事了
但偏偏我又多做了一個試驗
3恋捆、
如果實現(xiàn)協(xié)議的類帶了泛型呢?
Let's coding happily
class SuperVC<T>: 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<NSString> {
override var text: NSString? {get{return "范型~~~"} set{}}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print("滾動\(scrollView.contentOffset)")
print(text!)
}
}
輸出:
并沒有任何輸出扛门!
同問題1一樣子類跳過父類實現(xiàn)的協(xié)議方法并沒有被調(diào)用
而現(xiàn)在我只是多加了個泛型而已
試驗到這我已經(jīng)詞窮了鸠信, 一萬頭草泥馬纵寝,萬臉懵逼论寨。
問題
1、協(xié)議中的optional
方法, 實現(xiàn)的時候是通過何種方式派發(fā)的爽茴?
2葬凳、為什么自己實現(xiàn)的協(xié)議與系統(tǒng)表現(xiàn)的不一樣,系統(tǒng)提供的協(xié)議做了什么室奏?
3火焰、swift在編譯的過程中,對有范型的類除了做了泛型擦除還做了什么胧沫,以至于影響到了函數(shù)的派發(fā)昌简?