一. 对象
instance对象,也称实例对象
class对象,也称类对象
meta-calss对象,也称元类对象
本文将探讨如下问题:
- 这些对象中包含了什么信息
- 这些信息如何关联
- 成员变量是存在哪里的
- 类方法与实例方法是存在哪里的
- 如何找到superclass
instance对象
1. 什么是instance对象
通过+alloc
之后的都是instance
对象.这里还需要强调的是:instance
对象不仅仅是NSObject对象,还有一个代理类NSProxy,也能创建instance
对象
// 创建一个对象 NSObject* obj = [NSObject alloc];
Class对象
1. 获取class对象
创建一个继承自NSObject
的ClassObject
类
- (void)viewDidLoad { [super viewDidLoad]; ClassObject *clsObj = [[ClassObject alloc] init]; [self fetchClassWithClassObject:clsObj]; } //获取class的所有方法 - (void)fetchClassWithClassObject:(ClassObject *)clsObj { Class objClass1 = [clsObj class]; Class objClass2 = [ClassObject class]; Class objClass3 = object_getClass(clsObj); NSLog(@"\n objClass1 = %@ \n objClass2 = %@ \n objClass3 = %@ \n",NSStringFromClass(objClass1), NSStringFromClass(objClass2), NSStringFromClass(objClass3) ); NSLog(@"\n\n objClass1 = %p \n objClass2 = %p \n objClass3 = %p", objClass1, objClass2, objClass3); } //打印结果 2021-05-04 10:34:36.333929+0800 ClassDemo[26079:8911440] objClass1 = ClassObject objClass2 = ClassObject objClass3 = ClassObject 2021-05-04 10:34:36.334052+0800 ClassDemo[26079:8911440] objClass1 = 0x109a61548 objClass2 = 0x109a61548 objClass3 = 0x109a61548
打印可见,不管用什么方式获取的class对象都是一样的,打印地址也一致,说明在项目中一个Class仅有一个对象,但是上面三种获取class的方式有什么不同呢?
前两种是通过方法获取的,直接获取的是当前instance的Class, 但是第三种方式不一样,这种方式获取的是当前instance的isa的值
可以这样做个实验:给clsObj
添加一个kvo
[clsObj addObserver:self forKeyPath:@"class" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
打印结果变为
2021-05-04 10:54:32.415419+0800 ClassDemo[28990:8934226] objClass1 = ClassObject objClass2 = ClassObject objClass3 = NSKVONotifying_ClassObject 2021-05-04 10:54:32.415562+0800 ClassDemo[28990:8934226] objClass1 = 0x10fea3550 objClass2 = 0x10fea3550 objClass3 = 0x600001300240
第三个值变成了NSKVONotifying_ClassObject
2. class对象中的信息
- isa
- superclass
- 属性 property
- instance 方法
- 协议 protocal
- 成员变量,这里的成员变量信息并不是一个 instance 中成员变量的值,而是指在这个 Class 中有哪些成员变量,是 NSSting 的,还是 int 类型的
- 其它
meta-class 对象
1. 获取meta-class对象
在开发中是不会手动去+alloc
一个元类对象,可以通过object_getClass
函数获取class
的isa
类取之,代码如下
- (void)fetchMetaClassWithClassObject:(ClassObject *)clsObj { //1. 获取一个对象的isa Class objIsa = object_getClass(clsObj); //获取元类对象 Class metaClass = object_getClass(objIsa); NSLog(@" \n metaClass = %p \n metaClass = %@", metaClass, NSStringFromClass(metaClass)); }
会发现,元类还是当前的Class,但是是另一个对象地址
其次,不管是class对象还是元类对象,其类型都是Class,说明在内存结构上是一致的,但是其包含的信息含义是不一样的,其用途也不一样
meta-class 对象中的信息
- isa
- superclass
- 类方法信息
- 其它
对象总结
- 总共有三种对象:instance对象、class对象,meta-class对象
- 成员变量的值都存在instance中
- 属性、instance(实例)方法、协议protocol都存于class中
- 类方法都存于meta-class中
image
二. isa
以上的三种对象是如何关联起来的呢?是通过isa关联的:
instance对象的
isa
的值是class对象,class对象的isa
的值是meta-calss对象
既然实例方法是存在于class对象中,那么当给一个instance对象发送消息的时候,是如何找到具体的实现方法的呢?
当调用实例方法的时候,通过instance对象中的isa找到class,找到对应的实例方法的实现
同理,类方法的调用也是一样的:
当调用类方法时,通过class对象的isa指针找到meta-class, 并找到对应的类方法实现