彻底搞懂isa和superclass的作用

279 阅读4分钟

实例对象,类对象,元类对象的isa指向

instance的isa指向class

class的isa指向meta-class

meta-clas的isa指向基类的meta-class

类对象,元类对象的superclass指向

class的superclass指向父类的class

如果没有superclass则指向nil

meta-class的superclass指向父类的meta-class

特殊: 基类的meta-class的superclass指向基类的class

isa和superclass的作用

实例对象的isa和superclass的作用

eg,比如有对象Worker,继承自Person,Person继承自NSObject.创建Worker实例对象,调用eat对象方法

    Worker *w = [[Worker alloc]init];
    [w eat];
    
//    eat方法
    - (void)eat{
        NSLog(@"person eat %@",self);
    }

假设Worker有eat方法,那么会

  1. 通过worker实例的isa找到worker的class
  2. 在class的方法列表里面找,因为worker有eat方法,所以找到了,调用

note: 即使父类有eat方法也只会调用worker自身的

worker eat <Worker: 0x60000000ca20>

假设Worker没有eat方法,Person里面有

  1. 那么会通过worker的isa找到worker的class对象
  2. 在class对象的方法列表里面找,因为worker没有eat方法,找不到
  3. 通过worker的class对象的superclass找到Person的class对象
  4. 在Person的class对象的方法列表里面找,因Person有,找到了,调用

person eat <Worker: 0x60000000c660>

假设worker没有,person也没有,NSObject的分类里面有

  1. 那么会通过worker的isa找到worker的class对象
  2. 在class对象的方法列表里面找,因为worker没有eat方法,找不到
  3. 通过worker的class对象的superclass找到Person的class对象
  4. 在Person的class对象的方法列表里面找,因Person有,找不到
  5. 通过Person的class对象的superclass找到NSObject的class对象
  6. 在NSObject的class对象的方法列表中找,找到了,调用

NSObject eat <Worker: 0x600000008a00>

可以发现,调用者始终是worker

如果NSObject里面也没有,那么就会报错

-[Worker eat]: unrecognized selector sent to instance 0x600000008910

类对象的isa和superclass的作用

原理同上 只不过用类对象的isa找到的是meta-class,通过superclass找到的是父类的meta-class,另外这次我们调用的是class方法

[Worker drink];

// drink的实现如下
+ (void)drink{
    NSLog(@"worker drink %@",self);
}

假设worker有drink方法

  1. 通过worker的class对象的isa找到worker的meta-class
  2. 在meta-class的方法列表中找,找到,调用

worker drink Worker

假设worker没有,person有

  1. 通过worker的class对象的isa找到worker的meta-class
  2. 在meta-class的方法列表中找,找不到
  3. 通过worker的meta-class对象的superclass找到person的meta-class对象
  4. 在person的meta-class对象的方法列表中找,找到,调用

person drink Worker

假设worker没有,person没有,NSObject的分类有

  1. 通过worker的class对象的isa找到worker的meta-class
  2. 在meta-class的方法列表中找,找不到
  3. 通过worker的meta-class对象的superclass找到person的meta-class对象
  4. 在person的meta-class对象的方法列表中找,找不到
  5. 通过person的meta-class对象的superclass找到NSObject的meta-class对象
  6. 在NSObject的meta-class对象的方法列表中找,找到,调用

NSObject drink Worker

假设worker没有,person没有,NSObject的分类也没有

按照我们前面说的,类方法只存在于meta-class中,调用worker的类方法,会依次找worker,person,NSObject的meta-class,那假如连NSObject的meta-class也没有,正常来想应该会报错,让我们注释掉NSObject里面的drink实现,果然报错

+[Worker drink]: unrecognized selector sent to class 0x100002d50

假设worker没有,person没有,NSObject的分类也没有,但是NSObject却有一个名为drink的对象方法呢?

按照我们前面说的,类方法只存在于meta-class中,调用worker的类方法,会依次找worker,person,NSObject的meta-class,那假如连NSObject的meta-class也没有,NSObject却有一个名为drink的对象方法会发生什么呢?答案是会调用这个名为drink的对象方法

//NSObject的对象方法drink
- (void)drink{
    NSLog(@"对象方法 NSObject drink %@",self);
}

对象方法 NSObject drink Worker

果然打印了对象方法,这简直是太出人意料了,调用类方法最后却调用了对象方法,这是为什么呢?这也是官方示意图中root class的meta的superclass指向了自身的class对象的结果

官方示意图

meta的isa和superclass

meta-class的isa都指向根对象的meta-class,根对象的meta-class的isa指向自己,换成具体的例子就是

  1. worker的meta-class的isa指向NSObject的meta-class

  2. person的meta-class的isa指向NSObject的meta-class

  3. NSObject的meta-class的isa指向NSObject的meta-class

meta-class的superclass都指向

  1. worker的meta-class的superclass指向person的meta-class

  2. person的meta-class的superclass指向NSObject的meta-class

  3. NSObject的meta-class的superclass指向NSObject的class