Objective-C
中的对象,简称OC
对象,主要可以分为3
种
instance
对象(实例对象)class
对象(类对象)meta-class
对象(元类对象)instance
对象就是通过类alloc
出来的对象,每次调用alloc
都会产生新的instance
对象
NSObject *obj1 = [[NSObject alloc] init];
NSObject *obj2 = [[NSObject alloc] init];
NSLog(@"%p", obj1);
NSLog(@"%p", obj2);
打印结果会输出
0x1004992a0
0x1004974f0
由此可以看出,obj1
和obj2
是两个不同的对象,分别占据着两块不同的内存。
而instance
对象在内存中存储的信息包括
isa
指针_age = 5
,这个5
就是存在于实例对象中的查看以下代码中的内存地址
NSObject *object1 = [[NSObject alloc] init];
NSObject *object2 = [[NSObject alloc] init];
Class objectClass1 = [object1 class];
Class objectClass2 = [object2 class];
Class objectClass3 = [NSObject class];
Class objectClass4 = object_getClass(object1);
Class objectClass5 = object_getClass(object2);
在控制台调试打印地址
(lldb) p/x (long)objectClass1
(long) $2 = 0x00007fff8a20f140
(lldb) p/x (long)objectClass2
(long) $3 = 0x00007fff8a20f140
(lldb) p/x (long)objectClass3
(long) $4 = 0x00007fff8a20f140
(lldb) p/x (long)objectClass4
(long) $5 = 0x00007fff8a20f140
(lldb) p/x (long)objectClass5
(long) $6 = 0x00007fff8a20f140
经过调试可以发现5
个Class
类指向同一个地址值0x00007fff8a20f140
,它和instance
对象的区别是instance
对象是alloc
分配的内存空间,每个实例对象都占用不同的空间,但是Class
一个类只占用一份内存空间。
objectClass1
~objectClass5
都是NSObject
的Class
对象(类对象)Class
对象Class
对象在内存中存储的信息主要包括 isa
指针superclass
指针(@property)
(instance method)
(protocol)
(ivar)
class
和meta-class
内存地址值比较
Class objectClass = [NSObject class];
Class objectMetaClass = object_getClass([NSObject class]);
NSLog(@"%p", objectClass);
NSLog(@"%p", objectMetaClass);
0x7fff8a20f140
0x7fff8a20f0f0
对比发现,Class
和meta-class
的内存地址不一样。我们可以进行如下总结 :
objectMetaClass
是NSObject
的meta-class
对象(元类对象)meta-class
对象meta-class
对象和class
对象的内存结构是一样的,但是用途不一样,在内存总存储的主要信息包括 isa
指针superclass
指针(class method)
获取元类的内存地址只能通过object_getClass([NSObject class])
进行获取,通过[[NSObject class] class]
这种获取方法是错误的。
Class objectClass = [NSObject class];
Class objectWrongMetaClass = [[NSObject class] class];
Class objectMetaClass = object_getClass([NSObject class]);
NSLog(@"%p", objectClass);
NSLog(@"%p", objectWrongMetaClass);
NSLog(@"%p", objectMetaClass);
0x7fff8a20f140
0x7fff8a20f140
0x7fff8a20f0f0
instance(实例对象)
里。Class(类对象)
里。meta-class(元类对象)
里。根据上面可知,对象方法存储在class
的内存里,类方法存在于meta-class
内存里。问题来了,假如现在有一个Person
类的实例化对象p1
,如果想用p1
调用Person
类的对象方法personMethod
该如何调用呢?毕竟,p1
是存储在实例化对象instance
内存中的,而personMethod
方法是存储于Person
类的内存中的。
实际上instance
实例的对象的isa
指针指向class
,找到class
类以后,再在class
类中找存储于其中的对象方法
方法进行调用。
调用类方法的过程也是如此,class
类通过其内部的isa
指针找到meta-class
类中存储的类方法
,然后再进行调用。
至此,就可以回答上面的问题了。
instance
对象的isa
指向class
。 对象方法
时,通过instance
的isa
找到class
,再找到对象方法进行调用。class
对象的isa
指向meta-class
。 类方法
时,通过class
的isa
找到meta-class
,最后找到类方法
的实现进行调用。meta-class
对象的isa
指向基类的meta-class
对象。有如下两个类,继承关系如下 :
Student
->Person
->NSobject
@interface Person : NSObject
- (void)personMethod;
+ (void)personClassMethod;
@end
@implementation Person
- (void)personMethod {};
+ (void)personClassMethod {};
@end
@interface Student : Person
- (void)studentMethod;
+ (void)studentClassMethod;
@end
@implementation Student
- (void)studentMethod {};
+ (void)studentClassMethod {};
@end
创建一个实例student
Student *student = [[Student alloc] init];
[student studentMethod]
方法的过程- (void)studentMethod;
方法存在于Student
的class
内部。
student(实例对象)
的isa
指针找到Student
的class
。Student
的class
内部找到- (void)studentMethod;
方法并调用。[student personMethod]
方法的过程- (void)personMethod;
方法存在于Person
的class
内部。
student(实例对象)
的isa
指针找到Student
的class
。Student
的class
内部找是否存在- (void)personMethod;
方法。Student
的class
内的superclass
找到Person
的class
。Person
的class
内找是否存在- (void)personMethod;
方法。[student init]
方法的过程- (void)init;
方法存在于NSObject
的class
内部。
student(实例对象)
的isa
指针找到Student
的class
。Student
的class
内部找是否存在- (void)init;
方法。Student
的class
内的superclass
指针找到Person
的class
。Person
的class
内找是否存在- (void)init;
方法。Person
的class
内的superclass
指针找到NSObject
的meta-class
。NSObject
的class
内找是否存在- (void)init;
方法;有如下两个类,继承关系如下 :
Student
->Person
->NSobject
@interface Person : NSObject
- (void)personMethod;
+ (void)personClassMethod;
@end
@implementation Person
- (void)personMethod {};
+ (void)personClassMethod {};
@end
@interface Student : Person
- (void)studentMethod;
+ (void)studentClassMethod;
@end
@implementation Student
- (void)studentMethod {};
+ (void)studentClassMethod {};
@end
[Student studentClassMethod];
方法的过程+ (void)studentClassMethod;
方法存储在Student
的meta-class
内。
Student
类对象的isa
找到Student
的meta-class
。Student
的meta-class
内找类方法+ (void)studentClassMethod;
并调用。[Student personClassMethod];
方法的过程+ (void)personClassMethod;
方法存储在Person
的meta-class
内
Student
类对象的isa
找到Student
的meta-class
。Student
的meta-class
中不存在+ (void)personClassMethod;
方法。Student
的meta-class
内的superclass
找到Person
的meta-class
。Person
的meta-class
方法内找是否存在+ (void)personClassMethod;
方法。[Student load];
方法的过程+ (void)load;
是NSObject
的类方法。
Student
类对象的isa
找到Student
的meta-class
。Student
的meta-class
中不存在+ (void)load;
方法。Student
的meta-class
内的superclass
找到Person
的meta-class
。Person
的meta-class
方法内找是否存在+ (void)load;
方法。Person
的meta-class
内不存在+ (void)load;
方法。Person
的meta-class
内的superclass
找到NSObject
的meta-class
。NSObject
的meta-class
内找是否存在+ (void)load;
方法。下面是一张广为流传关于isa
、superclass
的经典图。
instance
的isa
指向class
class
的isa
指向meta-class
meta-class
的isa
指向基类的meta-class
class
的superclass
指向父类的class
superclass
指针为nil
meta-class
的superclass
指向父类的meta-class
meta-class
的superclass
指向基类的class
isa
找到class
,方法不存在,就通过superclass
找父类。
isa
找meta-class
方法不存在,就通过superclass
找父类。