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 */
};