在objc4-532.2以後,蘋果把nsobject的實現也挪進來了。想要了解nsobject底層實現終於不用去摳gnustep了~
好了,下面正文:
runtime裡面,宣告了id和class的型別,簡化一下如下:
1
2
3
4
5
6
7
8
9
structobjc_class;
structobjc_object;
typedefstructobjc_class *class;//類 (class object)
typedefstructobjc_object *id;//物件 (instance of class)
在objc中,id代表了乙個物件。根據上面的宣告,凡是首位址是*isa的struct指標,都可以被認為是objc中的物件。執行時可以通過isa指標,查詢到該物件是屬於什麼類(class)。
根據上面的說法,類物件(class)同樣也算是物件,那它的isa又是指向了什麼呢?為了了解這些東西是怎麼回事,這裡寫乙個簡單的類nyancat,並且用c重寫一遍,看看編譯器在底層到底是如何實現的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@inte***cenyancat : nsobject
-(void)nyan;
+(void)nyan;
@end
@implementationnyancat
-(void)nyan1
+(void)nyan2
@end
上面是乙個簡單的類,有兩個instance variable,有乙個類方法、乙個例項方法。
1
clang-rewrite-objc nyancat.m
在終端執行上面這一條語句,讓clang將該類重寫為cpp**,我們就能檢視到大概底層的實現機制了(實際編譯的檔案和這個會有些出入,不同目標架構和不同版本clang也會有不同..權且當參考了)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//class的實際結構
struct_class_t;
//class包含的資訊
struct_class_ro_t;
//nyancat(meta-class)
struct_class_t objc_metaclass_$_nyancat=;
//nyancat(class)
struct_class_t objc_class_$_nyancat=;
typedefstructobjc_object nyancat;//定義nyancat型別
//更詳細的不貼**了..
所有nyancat的例項的isa都指向了nyancat(class)。
nyancat(class)是乙個全域性變數,其中記錄了類名、成員變數資訊、property資訊、protocol資訊和例項方法列表等。
nyancat(class)的isa指向了全域性變數nyancat(meta-class),meta-class裡只記錄了類名、類方法列表等。
畫出圖來就是這樣:
舉例來說一下:
1
2
nyancat*cat=[[nyancatalloc]init];
[cat nyan1];
向cat (instance) 傳送訊息nyan1時,執行時會通過isa指標查詢到nyancat(class),這裡儲存著本類中定義的例項方法的指標。
1
[nyancatnyan2];
向nyancat(class)傳送訊息nyan2時,執行時會通過isa查詢到nyancat(meta-class),這裡儲存著本類中定義的類方法的指標。
執行時如何利用chass和meta-class來實現動態訊息的,以後在記吧~
在_class_t裡面,第二個成員是superclass,很明顯這個指標指向了它的父類。執行時可以通過isa和superclass獲取乙個類在繼承樹上的完整資訊。
為了說明方便,這裡把上面的例子稍微改一下:nyancat : cat : nsobject 這樣乙個繼承樹,畫出圖來就是這樣子的:
如上面圖中,跟隨黑線,可以看到isa的指向。執行時,每個物件的isa都不為空,這樣只要是乙個id型別的物件,runtime都可以通過訪問首位址偏移(isa)來獲取該物件的資訊了。
上圖中跟隨綠線,可以看到superclass的指向。當執行時在搜尋方法、ivar資訊時,如果沒有找到資訊,則會沿superclass的線查詢上去,最終nsobject(根類)的superclass是nil。
如果自己定義了乙個根類(比如nsproxy),則這個根類會替換圖中nsobject的位置。
為了驗證上面的說法,可以敲一下**看看:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#import "nyancat.h"
#import
#import
voidtest()
最後吐嘈一下:平時開發時,meta-class基本是用不著接觸的,superclass指標無法訪問,isa指標可能稍後也會隱藏起來(蘋果的動作真多)。。所以上面說得這些,了解一下就好~~
iOS學習筆記 Objective C 類和物件
inte ce myclass nsobject 方法宣告 id initwithstring nsstring aname myclass createmywithstring nsstring aname end在類的介面完成 h 定義乙個類 新增類的屬性 新增類的行為 方法 inte ce p...
Objective C物件之類物件和元類物件
作為c語言的超集,物件導向成為objective c與c語言的最大區別,因此,物件是objective c中最重要的部分之一。目前物件導向的語言有很多,objective c中的物件又和其他語言中的物件有什麼區別呢?下面來簡單介紹objective c中物件的實現。1 objective c中的類 ...
關於objective c中類的組合
關於objective c中類的組合問題,我們先來看一道題 1.設計2個類,類之間的關係自擬 比如繼承 組合 1 身材資料 1 屬性 身高 體重 手長 腳長 2 方法 屬性相應的set和get方法 2 人 1 屬性 年齡 身高 體重 手長 腳長 2 方法 屬性相應的set和get方法 思路 在這道題...