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的对象模型图:

相关文章
相关标签/搜索