super是一个编译指示器,仅仅是给编译器看的,不是一个指针。只要编译器看到super这个标志,就会让当前对象调用父类的方法,但是方法的调用者还是当前对象本身。
// ----- Model.h -----
#import <Foundation/Foundation.h>
@interface Model : NSObject
//仅仅开放一个方法,不实现
- (void)test;
@end
// ----- Model.m -----
#import "Model.h"
@implementation Model
@end
// ----- SubModel.h -----
#import "Model.h"
// 继承自Model
@interface SubModel : Model
@end
// ----- SubModel.m -----
#import "SubModel.h"
@implementation SubModel
// SubModel继承自Model,调用父类定义的方法test
- (void)test
{
// class: 获取class方法调用者的类
// superclass: 获取superclass方法调用者的父类
// super: 仅仅是一个编译指示器,就是给编译器看的,不是一个指针
// 本质:只要编译器看到super这个标志,就会让当前对象去调用父类方法,本质还是当前对象在调用
NSLog(@"self class:%@",[self class]);
NSLog(@"self superclass:%@",[self superclass]);
NSLog(@"super class:%@",[super class]);
NSLog(@"super superclass:%@",[super superclass]);
}
@end
// ------ ViewController.m ------
- (void)viewDidLoad {
[super viewDidLoad];
SubModel *subModel = [[SubModel alloc] init];
[subModel test];
}
调用结果
假如在SubModel中调用父类的test方法,将4个Log放入父类的test方法中,输出结果还是和上例一样。因为self还是SubModel对象,它仅仅只是调用了父类的方法。
// ------ SubModel.m ------
// SubModel继承自Model,调用父类定义的方法test
- (void)test
{
// class: 获取class方法调用者的类
// superclass: 获取superclass方法调用者的父类
// super: 仅仅是一个编译指示器,就是给编译器看的,不是一个指针
// 本质:只要编译器看到super这个标志,就会让当前对象去调用父类方法,本质还是当前对象在调用
// NSLog(@"self class:%@",[self class]);
// NSLog(@"self superclass:%@",[self superclass]);
// NSLog(@"super class:%@",[super class]);
// NSLog(@"super superclass:%@",[super superclass]);
//调用父类的test方法
[super test];
}
// ------ Model.m ------
- (void)test
{
//结果还是 SubModel Model SubModel Model, 虽然调用的是父类Model的test方法,self还是SubModel对象。
NSLog(@"self class:%@",[self class]);
NSLog(@"self superclass:%@",[self superclass]);
NSLog(@"super class:%@",[super class]);
NSLog(@"super superclass:%@",[super superclass]);
}
调用结果
super底层代码
- 新建一个命令行项目(Command Line Tool)
//main.m
#import <Foundation/Foundation.h>
@interface Model : NSObject
@end
@implementation Model
- (instancetype)init
{
self = [super init];
return self;
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"Hello, World!");
}
return 0;
}
- 打开终端,cd进包含main.m文件的文件夹(注意,这里是文件夹!!!),执行命令
clang -rewrite-objc main.m
,在该文件夹下会多出一个.cpp后缀的文件,打开该文件,cmd+F
,搜索@autoreleasepool
,找到底层实现代码
// main.cpp
#ifndef _REWRITER_typedef_Model
#define _REWRITER_typedef_Model
typedef struct objc_object Model;
typedef struct {} _objc_exc_Model;
#endif
struct Model_IMPL {
struct NSObject_IMPL NSObject_IVARS;
};
/* @end */
// @implementation Model
static instancetype _I_Model_init(Model * self, SEL _cmd) {
// 这里就是我们要找的底层代码
self = ((Model *(*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Model"))}, sel_registerName("init"));
return self;
}
// @end
int main(int argc, const char * argv[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
NSLog((NSString *)&__NSConstantStringImpl__var_folders_y5_y2q0fd790k900f9k1lxkz7ww0000gn_T_main_0aa3fc_mi_0);
}
return 0;
}
- super的底层实现代码
((Model *(*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Model"))}, sel_registerName("init"))
// 将强制类型转换全部删除掉
objc_msgSendSuper({self,class_getSuperclass(objc_getClass("Model"))},sel_registerName("init"))
objc_msgSendSuper(<#struct objc_super *super#>, <#SEL op, …#>) 第一个参数是个objc_super结构体,第二个参数是SEL
// receiver是指类的实例,super_class则是指该实例的父类
struct objc_super {
/// Specifies an instance of a class.
__unsafe_unretained id receiver;
/// Specifies the particular superclass of the instance to message.
#if !defined(__cplusplus) && !__OBJC2__
/* For compatibility with old objc-runtime.h header */
__unsafe_unretained Class class;
#else
__unsafe_unretained Class super_class;
#endif
/* super_class is the first class to search */
};