iOS:关于super 关键字(使用runtime分析)

创建一个 Father 类,再创建一个继承与 FatherSon 类。在 Son 中声明一个 exercise 方法打印 [self class][super class]
Father

//Father.h
#import 

NS_ASSUME_NONNULL_BEGIN

@interface Father : NSObject

@end

NS_ASSUME_NONNULL_END

//Father.m
#import "Father.h"

@implementation Father

@end

Son

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

NS_ASSUME_NONNULL_BEGIN

@interface Son : Father

- (void)exercise;

@end

NS_ASSUME_NONNULL_END

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

@implementation Son

- (void)exercise
{
    NSLog(@"\nself: %@\nsuper: %@",[self class],[super class]);
}

@end

创建 Son 对象,并调用方法 exercise

Son *son = [[Son alloc] init];
[son exercise];

打印结果

self: Son
super: Son

从结果来看可以发现在子类中打印 [self class][super class] 结果是相同的,都是打印调用者的 class 名称 Son
我们都知道 self 是类的隐藏参数,指向调用方法的这个类的实例,是一个 指针
superself 不一样,并不是指向父类的指针,只是一个 编译器修饰符 作用。

self 调用方法是从该类的方法列表当中找对应方法调用,如果没有就从父类当中找;而 super 关键词是从父类的方法列表当中找,调用父类的那个方法。但是这两种方式的事件调用者都是当前的实例 Son ,最终都是找到了 NSObject 中的 class 的方法。

runtime 的底层API来看调用 [self class] 的时候是调用了

objc_msgSend(self,@selector(class))

直接从当前实例里找class的实现。

调用 [super class] 的时候是调用了

objc_msgSendSuper(<#struct objc_super *super#>, <#SEL op, ...#>)

里面传两个参数,第一个参数objc_super结构体中有两个成员:

  • receiver: a pointer of type id. Specifies an instance of a class.
  • super_class: a pointer to a Class data structure. Specifies the particular superclass of the instance to the message.

receiver 就是调用这个事件的接受者 self,然后第二个就是父类的 class Father,然后从这个 Father 类开始找 class 方法,一直找到了 NSObject ,最后这两个方法都是调用了 [self class] 打印当前类的 class

你可能感兴趣的:(iOS:关于super 关键字(使用runtime分析))