理解 Self & Super

下面会打印什么?

- (id)init {
    self = [super init];
    if (self)
    {
        NSLog(@"%@", NSStringFromClass([self class]));
        NSLog(@"%@", NSStringFromClass([super class]));
    }
    return self;
 }
 @end
self:当前这个对象
super:编译器标示符,给编译器看的,底层用另外一个方法发消息
super就是self,去调用父类方法
让当前对象调用父类方法,本质上还是self在调用
  • 无论是[self class]还是[super class],接受消息者都是Son对象
    • super与self不同的是,self调用是在子类Son中找class方法
    • super调用是在父类Father中找class方法
  • 编译后,调用super标识符修饰的方法,会用objc_msgSendSuper函数进行消息的发送,而不是objc_msgSend


深度解析

调用[self class]方法时

  • 转化为objc_msgSend函数
  • 先在 Son 这个类里面去找- (Class)class方法,没有就去父类 Father里找,也没有,最后在 NSObject类中发现这个方法
NSObject类中- (Class)class的实现如下:
- (Class)class {
    // 返回实例的isa指针指向的类
    return object_getClass(self);
} 

[self class] == objc_msgSend(self, "class");
打印:Son


调用[super class]方法时

  • super为编译器标示符
  • 向super发送的消息被编译成objc_msgSendSuper
  • 不管是self、还是super指向消息接受者是一样的
转化为objc_msgSendSuper,函数定义如下:
id objc_msgSendSuper(struct objc_super *super, SEL op, ...) 
// objc_super的结构体
struct objc_super {
    id receiver;     
    Class super_class; // 记录当前父类
}; 
  • receiver,类的实例
    • objc_super->receiver=self
    • 消息的接受者还是self
  • super_class,记录当前类的父类
    • (id)class_getSuperclass(objc_getClass(“Son”))
      • 该函数输出结果为 Father
    • 去 Father这个类里去找- (Class)class,没有,然后去NSObject类去找
  • super只是告诉编译器,去查找父类中的class方法
    • 当找到之后,使用objc_super->receiver即self进行调用
[super class]转换流程

[super class] → objc_msgSendSuper(objc_super{self, superclass}, sel_registerName("class")) → objc_msgSend(objc_super->self, sel_registerName("class")) === [self class]
打印:Son



demo2:理解super

@implementation Father
- (void)test
{
    NSLog(@"%@, %@, %@", [self class], [self superclass], [super class]);
}
@end
--------------------------------
@implementation Son

/**
  class:获取方法调用者类名
  superclass:获取方法调用者的父类类名
  super:指向父类的标识,编译器修饰符,不是指针
 */
- (void)test
{
    // 谁调用这个方法,self就是谁!
    NSLog(@"%@", self);
//    NSLog(@"%@", super);
    // 函数里也没有定义super
    // self是隐藏参数,super就是个标识符,和const差不多!
//    NSLog(@"%@, %@, %@", [self class], [self superclass], [super class]);
    // Son, Father, Son
    
    [super test];
    // Son, Father, Son
}
@end
super不是父类对象!!
  • 和const差不多
  • self是对象、是指针可以打印,super不是指针,不能打印
  • 本质还是拿到当前对象去调用父类方法
  • super就是self去调用父类方法
  • 只是去父类方法里找,而不是找自己的


参考资料

  • 刨根问底Objective-C Runtime(1)- Self & Super

你可能感兴趣的:(理解 Self & Super)