Swift方法調度之類的普通方法底層探究
1. 類的普通方法調度
寫一個結構體和一個類,對比看看方法調用的方式:
// 結構體
struct PersonStruct {
func changClassName() {}
}
let s = PersonStruct()
s.changClassName()
// 類
class PersonClass {
func changClassName() {}
}
let c = PersonClass()
c.changClassName()
生成 SIL 代碼:
【1】結構體及類的 SIL 代碼:

與結構體不同的是:為PersonClass類自動生成了一個反初始化方法。
【2】執(zhí)行方法的 SIL 代碼:

在調用的方式中,可以看到類的方法,不是由function_ref修飾,而是class_method修飾。
【3】還有一個不同點是,SIL 中為 PersonClass 自動生成了sil_vtable:

由上面 SIL 代碼,我們可以看出,SIL 為類的方法創(chuàng)建了 sil_vtable,并在調用時,用class_method來修飾。這樣的類的方法調度,是Swift 中動態(tài)派發(fā)的一種方式,叫做函數(shù)派發(fā)。
這里由sil_vtable關鍵字聲明的就是函數(shù)表。函數(shù)表初始化的源碼如下:

從源碼中看,函數(shù)表中的數(shù)據(jù)結構是一個數(shù)組,源碼是以遍歷的的方式去獲取函數(shù)表內的函數(shù)的,所以函數(shù)表是按順序存放類中可能是函數(shù)派發(fā)去執(zhí)行的函數(shù),但是不一定函數(shù)表內的函數(shù)都會被以函數(shù)派發(fā)的方式去調度。
2. OC 繼承鏈中的方法列表存儲結構
我們知道OC 中的方法是消息派發(fā)的方式。 每個對象中都有一個 isa 指針,指向自己的類。類中存放著該類實現(xiàn)的方法列表。本類方法列表中存放著本類實現(xiàn)的方法及父類方法列表的指針。在消息派發(fā)時,會先查找本來的方法列表,如果沒找到,再去查找父類的方法列表,以此類推,來尋找方法的實現(xiàn)。
假設A類繼承B類,B類繼承C類,如下圖所示:

3. Swift 繼承連中的函數(shù)表存儲結構
Swift 類中函數(shù)派發(fā)與消息派發(fā)類似, 所有類也會維護一個自己的函數(shù)表,不同的是所有未被復寫的父類所實現(xiàn)的函數(shù)地址都會拷貝在這個表中, 而不是由一個指向父類方法表的指針替代,被重寫的函數(shù),在函數(shù)表中會指定為子類中的函數(shù)。由于少了一步指針尋址步驟, 在派發(fā)效率上要比基于消息的派發(fā)高效。
假設A類繼承B類,B類繼承C類,如下圖所示:

代碼驗證一下:
Swift
class PersonClass: NSObject {
override init() {
super.init()
@objc func changClassName7() {}
dynamic func changClassName8() {}
}
}
class PersonClassSub: PersonClass {
func runSub() {}
// 重寫的函數(shù),在函數(shù)表中會指定為子類中的函數(shù)
override func changClassName7() {}
}
class PersonClassSubSub: PersonClassSub {
func runSubSub() {}
}

到這里,證實2件事情:
- Swift的函數(shù)表是按順序存放的
- 在類的繼承關系中,函數(shù)表中存放所有的方法,由上到下,依次排列,先是父類的方法,再是子類的方法。
到此這篇關于Swift-方法調度-類的普通方法底層探究的文章就介紹到這了,更多相關Swift-方法調度內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Swift算法實現(xiàn)字符串轉數(shù)字的方法示例
最近學完了swift想著實踐下,就通過一些簡單的算法進行學習研究,下面這篇文章主要介紹了Swift算法實現(xiàn)字符串轉數(shù)字的方法,需要的朋友可以參考借鑒,下面來一起看看吧。2017-03-03
Swift 3.0將UILabel數(shù)字顏色設置為紅色的方法
這篇文章主要介紹了關于在Swift中將UILabel數(shù)字顏色設置為紅色的方法,文中給出了詳細的示例代碼,相信對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。2017-03-03

