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