美文网首页学习iOS面试题/2019
iOS-对象、isa指针、SuperClass

iOS-对象、isa指针、SuperClass

作者: Jey | 来源:发表于2018-12-06 16:46 被阅读30次

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找父类

2230763-c44c51bdc34f8645.png
总结:对象,类,元类的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指针

相关文章

网友评论

    本文标题:iOS-对象、isa指针、SuperClass

    本文链接:https://www.haomeiwen.com/subject/hnywcqtx.html