在Objective-C中,對象的類由isa指針標示,isa指向了對象的類。Objective-C中一個對象的基本定義以下: 函數
typedef struct objc_object { Class isa; } *id;
這就是說,任何起始於指向類的指針的數據類型,都被當作objc_object。因而,Objective-C中的全部類都被當作了對象。 spa
實際上,objc_class定義以下: 指針
typedef struct objc_class *Class; struct objc_class { Class isa; Class super_class; /* followed by runtime specific details... */ };
Meta-class與類類似,也是一個對象。類有實例對象,而類可看做是meta-class的實例,即類的isa指向它。它有這麼些特性,結合圖1進行理解。 code
l Meta-class包含了類的類方法; 對象
l 類和meta-class成對出現; 繼承
l Meta-class也有繼承關係; ci
l 每一個類都有屬於本身的惟一的meta-class; class
l 全部的meta-class的isa都指向基類的meta-class,基類的meta-class指向自身;基類的meta-class的父類是基類自身,即全部的類和meta-class都繼承自基類(NSObject)。 object
圖1 實例、類、Meta-class的關係圖 select
爲什麼須要meta-class?這與runtime的消息機制相關。
當向對象發送消息時,
3.1. 若對象爲實例對象:[instanceObj foo]
runtime根據isa找到所屬類。該類包含
一個實例方法列表(objc_method_list)
一個指向父類的指針,用於查找父類中的實例方法
查找過程:
在實例對象所屬的類中的方法列表中查找名爲foo的方法,若沒找到,在其父類中繼續查找,直到找到根類;若找到,則執行foo方法對應的IMP(函數指針)。若繼承關係鏈中的類都沒有,那麼會報錯誤:unrecognized selector sent to instance。其實runtime提供了3種解救方法,能夠動態新增方法或轉發消息。這裏不進行討論。
3.2. 對象是類對象:[classObj foo]
runtime根據isa找到所屬meta-class,它包含
一個類方法列表;
一個指向父類的指針,用於查找父類中的類方法
查找過程:
在類對象對應的meta-class的方法列表中查找名爲foo的方法,若沒找到,在其meta-class父類中繼續查找;若找到,則執行foo方法對應的IMP(函數指針)。若繼承關係鏈中的metal-class類都沒有,那麼會報錯誤:unrecognized selector sent to class。