iOS-对象、isa指针、SuperClass
OC中对象分类
分为三类:实例对象、类对象、元类对象
- instance对象(实例对象)
- class对象(类对象)
- meta-class对象(元类对象)
instance对象(实例对象)
- instance对象就是通过类alloc出来的对象,每次调用alloc都会产生新的instance对象
People *p1 = [[People alloc] init];
People *p2 = [[People alloc] init];
NSlog(@"%p",p1);
NSlog(@"%p",p2);
输出:
0x10010
0x20050
- p1、p2是Student的instance对象(实例对象),它们是不同的两个对象,分别占据着两块不同的内存
instance对象在内存中存储的信息包括
- isa指针
- 其他成员变量的值
- 实例对象不包含实现方法
类对象(Class)
NSObject *obj1 = [[NSObject alloc] init];
Class objClass1 = [obj1 class];
Class objClass2 = [NSObject class];
//class 方法返回的一直是class对象,类对象,而不是元类对象
Class objClass3 = [[NSObject class] class];
Class objClass4 = object_getClass(obj1);
NSLog(@"%p-%p-%p-%p",objClass1,objClass2,objClass3,objClass4);
打印出的地址相同,每个类在内存中有且只有一个class对象
class对象在内存中存储的信息包括
- isa指针
- superclass指针
- 类的属性信息(@property)
- 类的对象方法信息(instance method)
- 类的协议信息(protocol)
- 类的成员变量信息(ivar)(成员变量类型、名称等等,不是成员变量的值)
元类对象(meta-class)
// 获取元类对象
Class metaClass = object_getClass([NSObject class]);
在内存中存储的信息主要包括
- isa指针
- superclass指针
- 类的类方法信息(class method)
Class object_getClass(id obj)
1> 传入的obj可能是instance对象、class对象、meta-class对象
2> 返回值
a) 如果是instance对象,返回class对象
b) 如果是class对象,返回meta-class对象
c) 如果是meta-class对象,返回NSObject(基类)的meta-class对象
实例对象、类对象isa指向
instance的isa指向class,class的isa指向meta-class
- 当调用对象方法时,通过instance的isa找到class,最后找到对象方法的实现进行调用
- 当调用类方法时,通过class的isa找到meta-class,最后找到类方法的实现进行调用
OC的类信息存放在哪里?
- 对象方法、属性、成员变量、协议信息,存放在class对象中
- 类方法,存放在meta-class对象中
- 成员变量的具体值,存放在instance对象
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
-
instance调用对象方法的轨迹;isa找到class,方法不存在,就通过superclass找父类
-
class调用类方法的轨迹;isa找meta-class,方法不存在,就通过superclass找父类
总结:对象,类,元类的isa指针关系图
1、每一个对象本质上都是一个类的实例。其中类定义了成员变量和成员方法的列表。对象通过对象的isa指针指向所属类。
2、每一个类本质上都是一个对象,类其实是元类(meteClass)的实例。元类定义了类方法的列表。类通过类的isa指针指向元类。
3、元类保存了类方法的列表。当类方法被调用时,先会从本身查找类方法的实现,如果没有,元类会向他父类查找该方法。同时注意的是:元类(meteClass)也是类,它也是对象。元类通过isa指针最终指向的是一个根元类(root meteClass)。
4、根元类的isa指针指向本身,这样形成了一个封闭的内循环。
例子
#Person文件
@interface Person : NSObject
+ (void)test;
@end
@implementation Person
+ (void)test{
NSLog(@"+[Person test] %p",self);
}
@end
#NSObject+Test文件
@interface NSObject (Test)
+ (void)test;
@end
@implementation NSObject (Test)
+ (void)test{
NSLog(@"+[NSObject test] %p",self);
}
@end
#调用方式:
NSLog(@"Person:%p",[Person class]);
NSLog(@"NSObject:%p",[NSObject class]);
[Person test];
[NSObject test];
输出:
Person:0x10e72e090
NSObject:0x10f6d8ea8
+[Person test] 0x10e72e090
+[NSObject test] 0x10f6d8ea8
2、改下代码
#Person 文件
@interface Person : NSObject
+ (void)test;
@end
@implementation Person
//+ (void)test{
// NSLog(@"+[Person test] %p",self);
//}
@end
输出结果2:
Person:0x10477b050
NSObject:0x105725ea8
+[NSObject test] 0x10477b050
+[NSObject test] 0x105725ea8
因为Person里找不到test实现方法,即找父类的实现方法
3、修改
#Person 文件
@interface Person : NSObject
+ (void)test;
@end
@implementation Person
//+ (void)test{
// NSLog(@"+[Person test] %p",self);
//}
@end
#NSObject+Test文件
@interface NSObject (Test)
+ (void)test;
@end
@implementation NSObject (Test)
- (void)test{
NSLog(@"-[NSObject test] %p",self);
}
//+ (void)test{
// NSLog(@"+[NSObject test] %p",self);
//}
@end
输出结果3:
Person:0x101656010
NSObject:0x102600ea8
-[NSObject test] 0x101656010
-[NSObject test] 0x102600ea8
由此可见,当类方法无实现时,会调用同名的对象方法,上述辩证方法验证了isa、superclass指向meta-Root class的superclass指向Root class。
参考:iOS对象isa指针