iOS 关键字 self 和 super

先来看一个经典面试题:

以下代码输出什么?

// Son.h
#import "Father.h"

@interface Son : Father

@end

// Son.m
#import "Son.h"

@implementation Son

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

@end

答案是两个NSLog输出完全一样,都是 Son。这道面试题就是考察selfsuper的区别与联系。第一个NSLog输出Son肯定是不用说的。第二个输出中,[super class]输出Son就要说说selfsuper到底有什么小暧昧

self

  • self是一个隐藏参数变量

  • 这个指针指向当前调用方法的对象(即receiver)

  • self调用自己方法

  • self调用方法:

    • 当使用 self 调用方法时,会首先从当前类的方法列表中开始寻找,如果没有再去父类中寻找;
    • 当使用 self 调用方法时,runtime会将其转化为 objc_msgSend 函数:
      objc_msgSend(id receiver, SEL selector, ...)
      第一个参数是消息接收者,第二个参数是调用的具体方法的selector,后面是 selector 方法的可变参数。

super

  • super并不是隐藏参数,只是编译器的指令符号

  • super调用父类方法

  • super调用方法:

    • 当使用 super 调用方法时,从父类的方法列表中开始找,然后调用父类的这个方法。
    • 当使用 super 调用方法时,runtime会将其转化为 objc_msgSendSuper 函数:
      objc_msgSendSuper(struct objc_super *super, SEL op, ...)
      第一个参数是个objc_super的结构体,第二个参数还是类似objc_msgSend方法的selector。而objc_super的结构体如下:
      struct objc_super {
          __unsafe_unretained _Nonnull id receiver;
          __unsafe_unretained _Nonnull Class super_class;
      };
    
    • 当调用[super class]时,会被转换为下面的代码:
    struct objc_super objcSuper = {
      self,
      class_getSuperclass([self class])
    };
    
    id (*sendSuper)(struct objc_super*, SEL) = (void*)objc_msgSendSuper;
    
    sendSuper(&objcSuper, @selector(class));
    


由此可知,虽然调用的是[super class],但是调用方法和接受消息的对象还是self。然后来到父类Fatherclass方法中,输出self对应的类Son

你可能感兴趣的:(iOS 关键字 self 和 super)