Swift方法調(diào)度之類的普通方法底層探究
1. 類的普通方法調(diào)度
寫一個(gè)結(jié)構(gòu)體和一個(gè)類,對比看看方法調(diào)用的方式:
// 結(jié)構(gòu)體 struct PersonStruct { func changClassName() {} } let s = PersonStruct() s.changClassName() // 類 class PersonClass { func changClassName() {} } let c = PersonClass() c.changClassName()
生成 SIL 代碼:
【1】結(jié)構(gòu)體及類的 SIL 代碼:
與結(jié)構(gòu)體不同的是:為PersonClass類自動(dòng)生成了一個(gè)反初始化方法。
【2】執(zhí)行方法的 SIL 代碼:
在調(diào)用的方式中,可以看到類的方法,不是由function_ref修飾,而是class_method修飾。
【3】還有一個(gè)不同點(diǎn)是,SIL 中為 PersonClass 自動(dòng)生成了sil_vtable:
由上面 SIL 代碼,我們可以看出,SIL 為類的方法創(chuàng)建了 sil_vtable,并在調(diào)用時(shí),用class_method來修飾。這樣的類的方法調(diào)度,是Swift 中動(dòng)態(tài)派發(fā)的一種方式,叫做函數(shù)派發(fā)。
這里由sil_vtable關(guān)鍵字聲明的就是函數(shù)表。函數(shù)表初始化的源碼如下:
從源碼中看,函數(shù)表中的數(shù)據(jù)結(jié)構(gòu)是一個(gè)數(shù)組,源碼是以遍歷的的方式去獲取函數(shù)表內(nèi)的函數(shù)的,所以函數(shù)表是按順序存放類中可能是函數(shù)派發(fā)去執(zhí)行的函數(shù),但是不一定函數(shù)表內(nèi)的函數(shù)都會(huì)被以函數(shù)派發(fā)的方式去調(diào)度。
2. OC 繼承鏈中的方法列表存儲(chǔ)結(jié)構(gòu)
我們知道OC 中的方法是消息派發(fā)的方式。 每個(gè)對象中都有一個(gè) isa 指針,指向自己的類。類中存放著該類實(shí)現(xiàn)的方法列表。本類方法列表中存放著本類實(shí)現(xiàn)的方法及父類方法列表的指針。在消息派發(fā)時(shí),會(huì)先查找本來的方法列表,如果沒找到,再去查找父類的方法列表,以此類推,來尋找方法的實(shí)現(xiàn)。
假設(shè)A類繼承B類,B類繼承C類,如下圖所示:
3. Swift 繼承連中的函數(shù)表存儲(chǔ)結(jié)構(gòu)
Swift 類中函數(shù)派發(fā)與消息派發(fā)類似, 所有類也會(huì)維護(hù)一個(gè)自己的函數(shù)表,不同的是所有未被復(fù)寫的父類所實(shí)現(xiàn)的函數(shù)地址都會(huì)拷貝在這個(gè)表中, 而不是由一個(gè)指向父類方法表的指針替代,被重寫的函數(shù),在函數(shù)表中會(huì)指定為子類中的函數(shù)。由于少了一步指針尋址步驟, 在派發(fā)效率上要比基于消息的派發(fā)高效。
假設(shè)A類繼承B類,B類繼承C類,如下圖所示:
代碼驗(yàn)證一下:
Swift
class PersonClass: NSObject { override init() { super.init() @objc func changClassName7() {} dynamic func changClassName8() {} } } class PersonClassSub: PersonClass { func runSub() {} // 重寫的函數(shù),在函數(shù)表中會(huì)指定為子類中的函數(shù) override func changClassName7() {} } class PersonClassSubSub: PersonClassSub { func runSubSub() {} }
到這里,證實(shí)2件事情:
- Swift的函數(shù)表是按順序存放的
- 在類的繼承關(guān)系中,函數(shù)表中存放所有的方法,由上到下,依次排列,先是父類的方法,再是子類的方法。
到此這篇關(guān)于Swift-方法調(diào)度-類的普通方法底層探究的文章就介紹到這了,更多相關(guān)Swift-方法調(diào)度內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Swift利用純代碼實(shí)現(xiàn)時(shí)鐘效果實(shí)例代碼
這篇文章主要給大家介紹了關(guān)于Swift利用純代碼實(shí)現(xiàn)時(shí)鐘效果的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用swift具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-05-05Swift編程中實(shí)現(xiàn)希爾排序算法的代碼實(shí)例
希爾排序是對插入排序的一種改進(jìn)版本,算法本身并不穩(wěn)定,存在優(yōu)化空間,這里我們來講一下希爾排序的大體思路及Swift編程中實(shí)現(xiàn)希爾排序算法的代碼實(shí)例2016-07-07Swift編程中的switch...case語句實(shí)例解析
這篇文章主要介紹了Swift編程中的switch...case語句實(shí)例解析,其中重點(diǎn)還是對于fallthrough關(guān)鍵字用法的講解,需要的朋友可以參考下2016-04-04利用Swift實(shí)現(xiàn)一個(gè)響應(yīng)式編程庫
最近在學(xué)習(xí)swift,最近有空所以總結(jié)一下最近學(xué)習(xí)的內(nèi)容,下面這篇文章主要給大家介紹了關(guān)于利用Swift實(shí)現(xiàn)一個(gè)響應(yīng)式編程庫的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。2017-12-12Swift開發(fā)之使用UIRefreshControl實(shí)現(xiàn)下拉刷新數(shù)據(jù)及uirefreshcontrol使用
本文給大家介紹使用UIRefreshControl實(shí)現(xiàn)下拉刷新數(shù)據(jù),及UIRefreshControl的使用步驟,對本文感興趣的朋友一起學(xué)習(xí)吧2015-11-11iOS Swift UICollectionView橫向分頁滾動(dòng),cell左右排版問題詳解
UICollectionView是iOS中比較常見的一個(gè)控件,這篇文章主要給大家介紹了關(guān)于iOS Swift UICollectionView橫向分頁滾動(dòng),cell左右排版問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-12-12Swift之UITabBarController 導(dǎo)航控制器的自定義
本文給大家介紹swift導(dǎo)航控制器之UITabBarController,本文通過代碼實(shí)例給大家講解swift導(dǎo)航控制器,導(dǎo)航控制器類繼承UITabBarController,代碼簡單易懂,需要的朋友可以參考下2015-10-10