object_getClass(obj)與[obj class]的區別在Object-C的類型結構中

在Object-C的類型結構中,有幾個比較重要的概念:Object(實例),Class(類),Metaclass(元類),Rootclass(根類),Rootclass‘s metaclass(根元類),且這些都是對象。所以標題中的「obj」這個對象能夠是上面五個概念的任意一個,須要一一探討。
測試

1.obj爲Object實例對象
在Object-C中,Object本質上是一個struct,在這個struct中會保存一個名爲isa的指針,該指針會指向該Object的類。定義以下所示:指針

    typedef struct objc_object {  
         Class isa;  
    } *id;

下面是代碼測試:code

    //obj爲實例變量
    id obj = [TestObject new];

    Class cls = object_getClass(obj);

    Class cls2 = [obj class];   
    
    NSLog(@"%p" , cls);    NSLog(@"%p" , cls2);

輸出結果:對象

    2015-12-17 14:08:32.196 TestProject[658:29503] 0x100001140
    2015-12-17 14:08:32.197 TestProject[658:29503] 0x100001140

結論:當obj爲實例變量時,object_getClass(obj)與[obj class]輸出結果一直,均得到isa指針,即指向類對象的指針。ci

2.obj爲Class類對象
在Objective-C中,任何類的定義都是對象。類和類的實例(對象)沒有任何本質上的區別。任何對象都有isa指針。get

    typedef struct objc_class *Class;    struct objc_class {
          Class isa;
          Class super_class;         
          /* followed by runtime specific details... */
   };

下面是代碼測試:class

    //obj爲實例變量
    id obj = [TestObject new];    
    
    //classObj爲類對象
    Class classObj = [obj class];

    Class cls = object_getClass(classObj);    
    Class cls2 = [classObj class];

    NSLog(@"%p" , cls);    
    NSLog(@"%p" , cls2);

輸入結果:變量

    2015-12-17 14:25:48.785 TestProject[813:38336] 0x100001118
    2015-12-17 14:25:48.786 TestProject[813:38336] 0x100001140

結論:當obj爲類對象時,object_getClass(obj)返回類對象中的isa指針,即指向元類對象的指針;[obj class]返回的則是其自己。object

3.obj爲Metaclass類對象
Metaclass與Class的結構是同樣的,只是職能不一樣。Class結構中是存儲Object實例的相關數據,而Metaclass則是存儲Class相關的數據。meta

下面的測試代碼:

     //obj爲實例變量
    id obj = [TestObject new];    
    
    //classObj爲類對象
    Class classObj = [obj class];
    
    //metaClassObj爲元類對象
    Class metaClassObj = object_getClass(classObj);    
    Class cls = object_getClass(metaClassObj);    
    Class cls2 = [metaClassObj class];

    NSLog(@"%p" , cls);    
    NSLog(@"%p" , cls2);

輸出結果:

    2015-12-17 14:41:23.386 TestProject[921:47694] 0x7fff78fb9118
    2015-12-17 14:41:23.387 TestProject[921:47694] 0x100001118

結論:當obj爲Metaclass(元類)對象時,object_getClass(obj)返回元類對象中的isa指針,由於元類對象的isa指針指向根類,全部返回的是根類對象的地址指針;[obj class]返回的則是其自己。

4.obj爲Rootclass類對象
Rootclass顧名思義就是根類,任何類的Metaclass中的isa指針都是指向根類。且結構與Class結構是同樣的。

測試代碼:

    //obj爲實例變量
    id obj = [TestObject new];    
    
    //classObj爲類對象
    Class classObj = [obj class];
    
    //metaClassObj爲元類對象
    Class metaClassObj = object_getClass(classObj);    
    
    //rootClassObj爲元類對象
    Class rootClassObj = object_getClass(metaClassObj);    
    Class cls = object_getClass(rootClassObj);    
    Class cls2 = [rootClassObj class];

    NSLog(@"%p" , cls);    
    NSLog(@"%p" , cls2);


輸出結果:

    2015-12-17 14:52:34.633 TestProject[965:54693] 0x7fff78fb9118
    2015-12-17 14:52:34.634 TestProject[965:54693] 0x7fff78fb9118

結論:當obj爲Rootclass(元類)對象時,object_getClass(obj)返回根類對象中的isa指針,由於根類對象的isa指針指向Rootclass‘s metaclass(根元類),即返回的是根元類的地址指針;[obj class]返回的則是其自己。
由於根類的isa指針實際上是指向自己的,全部根元類其實就是根類,全部輸出的結果是同樣的。

總結:經上面初步的探索得知,object_getClass(obj)返回的是obj中的isa指針;而[obj class]則分兩種狀況:一是當obj爲實例對象時,[obj  class]中class是實例方法:- (Class)class,返回的obj對象中的isa指針;二是當obj爲類對象(包括元類和根類以及根元類)時,調用的是類方法:+ (Class)class,返回的結果爲其自己。

最後,奉上一張經典的Object-C的對象模型圖:

相關文章
相關標籤/搜索