创建一个 Father 类,再创建一个继承与 Father 的 Son 类。在 Son 中声明一个 exercise 方法打印 [self class]和[super class]
Father 类
//Father.h
#import <Foundation/Foundation.h>
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 是类的隐藏参数,指向调用方法的这个类的实例,是一个 指针。
而 super 跟 self 不一样,并不是指向父类的指针,只是一个 编译器修饰符 作用。
用 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 typeid. Specifies an instance of a class.super_class: a pointer to aClassdata structure. Specifies the particular superclass of the instance to the message.
receiver 就是调用这个事件的接受者 self,然后第二个就是父类的 class Father,然后从这个 Father 类开始找 class 方法,一直找到了 NSObject ,最后这两个方法都是调用了 [self class] 打印当前类的 class。