天天看點

Swift-方法排程-類的普通方法底層探究

寫一個結構體和一個類,對比看看方法調用的方式:

生成 SIL 代碼:

【1】結構體及類的 SIL 代碼:

Swift-方法排程-類的普通方法底層探究

與結構體不同的是:為PersonClass類自動生成了一個反初始化方法。

【2】執行方法的 SIL 代碼:

Swift-方法排程-類的普通方法底層探究

在調用的方式中,可以看到類的方法,不是由function_ref 修飾,而是class_method修飾。

【3】還有一個不同點是,SIL 中為 PersonClass 自動生成了sil_vtable:

Swift-方法排程-類的普通方法底層探究

由上面 SIL 代碼,我們可以看出,SIL 為類的方法建立了 sil_vtable,并在調用時,用class_method來修飾。這樣的類的方法排程,是Swift 中動态派發的一種方式,叫做函數派發。

這裡由sil_vtable 關鍵字聲明的就是函數表。 函數表初始化的源碼如下:

Swift-方法排程-類的普通方法底層探究

從源碼中看,函數表中的資料結構是一個數組,源碼是以周遊的的方式去擷取函數表内的函數的,是以函數表是按順序存放類中可能是函數派發去執行的函數,但是不一定函數表内的函數都會被以函數派發的方式去排程。

我們知道 OC 中的方法是消息派發的方式。 每個對象中都有一個 isa 指針,指向自己的類。類中存放着該類實作的方法清單。本類方法清單中存放着本類實作的方法及父類方法清單的指針。在消息派發時,會先查找本來的方法清單,如果沒找到,再去查找父類的方法清單,以此類推,來尋找方法的實作。

假設A類繼承B類,B類繼承C類,如下圖所示:

Swift-方法排程-類的普通方法底層探究

Swift 類中函數派發與消息派發類似, 所有類也會維護一個自己的函數表, 不同的是所有未被複寫的父類所實作的函數位址都會拷貝在這個表中, 而不是由一個指向父類方法表的指針替代, 被重寫的函數,在函數表中會指定為子類中的函數。由于少了一步指針尋址步驟, 在派發效率上要比基于消息的派發高效。

Swift-方法排程-類的普通方法底層探究

代碼驗證一下:

Swift

Swift-方法排程-類的普通方法底層探究

到這裡,證明2件事情:

Swift的函數表是按順序存放的

在類的繼承關系中,函數表中存放所有的方法,由上到下,依次排列,先是父類的方法,再是子類的方法。

以上為這篇文章的全部内容了,希望本文的内容對大家的學習或者工作具有一定的參考學習價值,謝謝大家支援。

青山不改,綠水長流,後會有期,感謝每一位佳人的支援!