子類爲何能夠經過類方法調用NSObject 中的實例方法
- 當咱們在NSObject 中使用分類建立一個實例方法的時候,咱們發現繼承子NSObject的子類DNPerson 能夠經過 類方法調用這個實例方法 這裏涉及的知識點覆蓋了方法查找流程整個查找過程是很是值得咱們研究的,接下來讓咱們一塊兒研究一下
準備工做
建立了一個繼承自NSObject 的分類 ,其中主要有三個方法函數
- 一個實例方法,後續咱們須要在找到這個方法到底被存在了哪裏
- printMethods 輸出當前class 的方法列表 打印方法名稱
- 獲取類、元類、根元類 以及根元類的superClass
.m文件中實現 cdn
建立NSObject子類DNPerson ,值得注意的是DNPerson中咱們聲明瞭3個方法,可是咱們只實現了2個,那麼沒有實現的方法會存儲在哪裏呢?
方法查找流程解析:
問題本質實際上是關於oc中對象數據存儲的相關知識:對象
- 實例對象的實例變量是存在實例對象裏的
- 實例方法是以實例存在實例對象isa指向的類對象裏
- 類方法是以實例存在類對象isa指向的元類對象裏
isa 指向和Class的繼承關係以下圖所示:blog
代碼堆棧信息解析
執行 [NSObject PrintClassChain: [DNPerson class]]; PrintClassChain ,中咱們經過object_getClass 函數獲取cls->ISA() 函數控制檯打印以下繼承
- 咱們能夠看到DNPerson 中的 實例方法存儲在元類的方法列表中,同時咱們也能夠發現@property也是至關於存儲了一個set 以及一個get 的實例方法
- 類方法dnTestClassMethod,存儲在類元類方法列表中
- 未實現的方法沒有被存儲
接下來咱們來看下根元類中的方法打印信息 get
能夠發現,根元類中只打印了類方法,此時根元類的class 爲NSObject, 根元類superClass的方法列表打印以下
在這裏咱們發現了,NSObject 的實例方法,也就是說當咱們在元類中查找方法直到根雲類中也沒有找到方法的時候會去NSObject 的類方法中查找一下,這也是爲何,繼承NSObject 的子類能夠執行經過類方法執行實例方法的緣由