OC的对象分为三类:
- instance对象(实例对象)
- class对象(类对象)
- meta-class对象(元类对象)
实例对象
instance对象就是通过类alloc出来的对象,每次调用alloc都会产生新的instance对象,每个实例对象的内存地址都不一样
int main(int argc, char * argv[]) {
@autoreleasepool {
//实例对象
NSObject *object1 = [[NSObject alloc] init];
NSObject *object2 = [[NSObject alloc] init];
//实例对象内存地址打印
NSLog(@"%p %p",object1,object2);
//0x28039c180 0x28039c170,内存地址不一样。说明实例对象是不同的
}
return 0;
}
instance实例对象只保存成员变量
class类对象
通过class方法或runtime方法得到一个class对象
int main(int argc, char * argv[]) {
@autoreleasepool {
//类对象,一个类对象是唯一的,在内存中只有一份
Class objectClass1 = [object1 class];
Class objectClass2 = [object2 class];
Class objectClass3 = [NSObject class];
Class objectClass4 = object_getClass(object1);
Class objectClass5 = object_getClass(object2);
//类对象内存地址打印
NSLog(@"%p %p %p %p %p",
objectClass1,objectClass2,objectClass3,objectClass4,objectClass5);
//0x1e3d9beb0 0x1e3d9beb0 0x1e3d9beb0 0x1e3d9beb0 0x1e3d9beb0,内存地址都一样,说明在内存中只有一个类对象
}
return 0;
}
可以看到不管用什么方法生成的类对象的内存地址都是一样的,说明每一个类在内存中有且只有一个class对象。
之前提到instance实例对象不保存方法,只保存成员变量。方法保存在class类对象中
类对象中主要包含:
- isa指针
- superclass指针
- 类的属性信息(@property),如成员变量的类型
- 类的对象方法信息
- 类的协议信息(protocol)
- 类的成员变量信息(ivar)
成员变量的值是存储在实例对象中的,因为只有当我们创建实例对象的时候才为成员变赋值。但是成员变量叫什么名字,是什么类型,只需要有一份就可以了。所以存储在class对象中。
元类对象 meta-class
通过runtime方法object_getClass传入一个类对象得到元类对象
int main(int argc, char * argv[]) {
@autoreleasepool {
NSObject *object1 = [[NSObject alloc] init];
NSObject *object2 = [[NSObject alloc] init];
//元类对象,将类对象当作参数,获得元类对象,每个类中也只有一个元类对象,在内存是唯一的
Class objectMetaClass1 = object_getClass([NSObject class]);
Class objectMetaClass2 = object_getClass([NSObject class]);
NSLog(@"metaclass - %p %p",objectMetaClass1,objectMetaClass2);
//0x1e3d9be60 0x1e3d9be60
}
return 0;
}
通过打印的内存地址可以知道 每个类中也只有一个元类对象,在内存是唯一的
meta-class元类对象保存的内容与类对象类似,主要是
- isa指针
- superclass指针
- 类的类方法信息
注:我们知道用class方法可以获得class类对象,但是类对象调用class方法依旧是类对象,而不是元类对象
Class objectClass3 = [NSObject class];//这是一个类对象
Class objectClass2 = [[NSObject class] class];//这是一个类对象,而不是元类对象
NSLog(@"class - %p %p", objectClass3, objectClass2);//class - 0x1e3d9be60,0x1e3d9be60
以上代码可以看到,类对象调用class方法后还是一个类对象,而并不是元类对象,只有通过runtime方法object_getClass传入一个类对象才得到元类对象
总结:每一个类可以有多个实例对象,但是对应只有一个类对象和元类对象。
网友评论