Runtime-(二)对象,类对象,元类对象

类对象存储实例方法列表等信息
元类对象存储类方法列表等信息

先献祭出一副官方的图

Runtime-(二)对象,类对象,元类对象_第1张图片
Xnip2018-10-24_14-20-41.png

这幅图相信大多数做iOS的都不会陌生。

这里,我们就来描述一下图中所表述的isa以及superclass的指向情况。

首先,我们在上面的内容中,已经知道了所有的类实际上都是一个对象,我们称之为类对象。当我们声明实例的时候,所声明的实例对象的isa指针就指向这些类对象,这些类对象存储了实例方法(也就是-方法),而这些类对象也拥有isa指针,他们的指向了MetaClass对象。这些MetaClass对象负责存储类类方法(+方法)。与类对象样,MetaClass也是objc_class结构,所以也拥有isa指针,这些isa指针都指向根元类对象(Root MetaClass),
而根元类对象的isa指针指向根元类对象本身。这样就构成了一个闭环。

再看看superclass指针,首先对于类对象,是一层层的继承关系。各自的superclass指向其父类,类对象的最顶层superclass指向nil,对于元类对象也是直线各自的父类。这里需要重点说明的是,根元类对象的superclass指向的是其类对象。也就是说,当根元类对象在查找类方法中没找到对应的方法,那么就会去实例方法列表中去查找。

我们来分析例子,如果我们调用最下层(最左下角)的实例的实例方法,方法的查找流程是怎样的?

  • 先根据isa指针找到类对象,遍历类对象中的方法列表
  • 没找到依次查找父类的方法列表
  • 到nil

再如果我们调用最下层(最左下角)的实例的类方法,方法的查找流程是怎样的?

  • 先根据isa找到类方法
  • 再找到类方法的isa指针指向的MetaClass,遍历类方法列表
  • 没找到依次查找父类的方法列表
  • 直到根元类都未找到时,查找根类对象
  • 到nil

到这里,应该可以理解实例对象的方法查找流程,与类方法的方法查找流程了吧!

再来看一个面试题

#import "Father.h"

@interface Son: Father

@end

@implementation Son
- (instancetype)init {
    self = [super init];
    if (self) {
        NSLog(@"%@", NSStringFromClass([self class]));
        NSLog(@"%@", NSStringFromClass([super class]));
    }
    return self;
}
@end

上面的面试题的答案是打印2个Son。我们来分析一下。

class方法的的实现是在NSObject当中的,所以这两个方法的class方法最终都要调用到NSObject的class方法。而super这个关键字,实际上返回的消息接受者依然是Son,所以两个的输出是相同的。只不过是从当前类对象(Son的类对象)的父类对象(Father的类对象)开始查找方法实现。

你可能感兴趣的:(Runtime-(二)对象,类对象,元类对象)