Objective-C中的对象,简称OC对象,主要分为3种:
1)instance对象----实例对象
instance对象就是通过类alloc出来的对象,每次调用alloc都会产生新的instance对象。
instance对象中包含了:
* isa指针
* 成员变量的值
2)class对象----类对象
每个类在内存中只有一个类对象。可通过三种方法获得:
1.实例对象调用class方法(Class c1 = [a class])
2.类调用class方法(Class c2 = [Animal class])
3.使用object_getClass方法获取(Class c3 = object_getClass(a))
class对象中包含了:
* isa指针
* superclass指针
* 类的属性信息(@property)
* 类的对象方法信息(instance method)
* 类的协议信息(protocol)
* 类的成员变量信息(ivar)
3)meta-class对象----元类对象
每个类内存中只有一个元类对象。可通过以下的方法获取:
Class metaCls = object_getClass([NSObject class]);
元类对象和类对象的内存结构是一样的,但用途不一样,元类对象中包含了:
* isa指针
* superclass指针
* 类的类方法信息(class method)
Tips:元类对象object_getClass([NSObject class])来获取,不能通过[[NSObject class] class]来获取。
从上面的知识我们就可以就看出来:
1. 成员变量具体的值,放在instance对象(实例对象)里。
2. 属性信息、对象方法信息、协议信息、成员变量信息,放在Class对象(类对象)里。
3. 类方法信息,放在meta-class对象(元类对象)里。
根据信息的存放,我们可以得到对象方法存储在class的内存里,类方法存在于meta-class内存里。
那么问题来了,假如现在有一个Animal类的实例化对象a1,如果想用a1调用Animal类的对象方法animalMethod该如何调用呢?毕竟,a1是存储在实例化对象instance内存中的,而animalMethod方法是存储于Animal类的内存中的。
实际上instance实例的对象的isa指针指向class,找到class类以后,再在class类中找存储于其中的对象方法方法进行调用。
调用类方法的过程也是如此,class类通过其内部的isa指针找到meta-class类中存储的类方法,然后再进行调用。
至此,就可以回答上面的问题了。
调用[a1 animalMethod]方法的过程
- (void)animalMethod;方法存在于Animal的class内部。
通过a1(实例对象)的isa指针找到Animal的class。
在Animal的class内部找到- (void)animalMethod;方法并调用。
isa、superclass 总结
下面是一张广为流传关于isa、superclass的经典图。
isa
instance的isa指向class
class的isa指向meta-class
meta-class的isa指向基类的meta-class
superclass
class的superclass指向父类的class
如果没有父类,superclass指针为nil
meta-class的superclass指向父类的meta-class
基类的meta-class的superclass指向基类的class
instance 调用对象方法的轨迹
isa找到class,方法不存在,就通过superclass找父类。
class 调用类方法的轨迹
isa找meta-class方法不存在,就通过superclass找父类。