在平時的開發過程中,我們經常會執行[super xxx]
來調用父類的方法,但是我們很少會去關心super
關鍵字的底層是如何實現的,接下來我們來看下super
關鍵字底層實現原理,我們新建一個工程,然后創建Person
類和Student
類,Student類繼承自Person類,示例代碼如下:
Person
類
@interface Person : NSObject
- (void)run;
@end
@implementation Person
- (void)run {
NSLog(@"%s", __func__);
}
@end
Student
類
@interface Student : Person
@end
@implementation Student
- (instancetype)init {
if (self = [super init]) {
NSLog(@"%@", [self class]); // Student
NSLog(@"%@", [self superclass]); // Person
NSLog(@"%@", [super class]); // Student
NSLog(@"%@", [super superclass]); // Person
}
return self;
}
- (void)run {
[super run];
NSLog(@"%s", __func__);
}
@end
main
函數:
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
Student *stu = [[Student alloc] init];
[stu run];
}
return 0;
}
接下來我們執行命令xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 Student.m
將Student.m
文件轉換為底層c++文件,轉換為底層的run
方法代碼如下:
static void _I_Student_run(Student * self, SEL _cmd) {
((void (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))}, sel_registerName("run"));
NSLog((NSString *)&__NSConstantStringImpl__var_folders_lr_81gwkh751xzddx_ffhhb5_0m0000gn_T_Student_18b3ae_mi_0, __func__);
}
我們將Studnnt
類的run
方法進行簡化如下:
- (void)run {
[super run];
/**
結構體objc_super包含兩個成員:
self:消息接收者(receiver)
class_getSuperclass(objc_getClass("Student")):消息接收者的父類(super_class)
*/
struct objc_super superStruct = {
self,
class_getSuperclass(objc_getClass("Student"))
};
objc_msgSendSuper(superStruct, sel_registerName("run"));
NSLog(@"%s", __func__);
}
我們發現當我們在run
函數中執行[super run]
后,最終底層轉換為objc_msgSendSuper()
消息發送,我們通過底層源碼看下objc_msgSendSuper
函數的定義,查找路徑objc4 -> message.h -> objc_msgSendSuper
,具體底層函數定義如下:
/**
* Sends a message with a simple return value to the superclass of an instance of a class.
*
* @param super A pointer to an \c objc_super data structure. Pass values identifying the
* context the message was sent to, including the instance of the class that is to receive the
* message and the superclass at which to start searching for the method implementation.
* @param op A pointer of type SEL. Pass the selector of the method that will handle the message.
* @param ...
* A variable argument list containing the arguments to the method.
*
* @return The return value of the method identified by \e op.
*
* @see objc_msgSend
*/
OBJC_EXPORT id _Nullable
objc_msgSendSuper(struct objc_super * _Nonnull super, SEL _Nonnull op, ...)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
我們從源碼objc_msgSendSuper
函數定義可以看到,函數接受兩個參數
- objc_super
- SEL
我們再來看下objc_super
結構體底層定義如下:
/// Specifies the superclass of an instance.
struct objc_super {
/// Specifies an instance of a class.
// 消息接收者
__unsafe_unretained _Nonnull 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 _Nonnull Class class;
#else
// 消息接收者的父類
__unsafe_unretained _Nonnull Class super_class;
#endif
/* super_class is the first class to search */
};
簡化objc_super
結構體如下:
/**
從`objc_msgSendSuper`函數的注釋可以看到結構體的兩個成員含義:the instance of the class that is to receive the message and the superclass at which to start searching for the method implementation.
*/
struct objc_super {
// receiver就是消息接收者 (the instance of the class that is to receive the message)
__unsafe_unretained _Nonnull id receiver;
// super_class就是消息接收者的父類 (官方解釋:the superclass at which to start searching for the method implementation)
__unsafe_unretained _Nonnull Class super_class;
};
通過objc_super
底層定義,我們可以看到這個結構體也包含兩個成員
- receiver
- super_class
我們通過objc_msgSendSuper
函數底層定義的注釋中可以查看到參數objc_super
結構體中兩個成員的具體含義和作用
instance of the class that is to receive the message and the superclass at which to start searching for the method implementation
從上面注釋我們了解到receiver
就是消息的接受者(也就是方法調用者),superclass
就是指從父類開始查找方法
因此在Student
的init
初始化函數中打印結果如下:
- (instancetype)init {
if (self = [super init]) {
NSLog(@"%@", [self class]); // Student
NSLog(@"%@", [self superclass]); // Person
NSLog(@"%@", [super class]); // Student
NSLog(@"%@", [super superclass]); // Person
}
return self;
}
class
和superclass
函數的底層源碼實現:
- (Class)class {
// self為方法調用者,也就是消息接收者(receiver),返回當前方法調用者的類對象
return object_getClass(self);
}
- (Class)superclass {
// self為方法調用者,也就是消息接收者(receiver),返回當前方法調用者的父類對象
return return self->superclass;
}
講解示例Demo地址:https://github.com/guangqiang-liu/07.2-RunTimeSuper
更多文章
- ReactNative開源項目OneM(1200+star):https://github.com/guangqiang-liu/OneM:歡迎小伙伴們 star
- iOS組件化開發實戰項目(500+star):https://github.com/guangqiang-liu/iOS-Component-Pro:歡迎小伙伴們 star
- 簡書主頁:包含多篇iOS和RN開發相關的技術文章http://www.lxweimin.com/u/023338566ca5 歡迎小伙伴們:多多關注,點贊
- ReactNative QQ技術交流群(2000人):620792950 歡迎小伙伴進群交流學習
- iOS QQ技術交流群:678441305 歡迎小伙伴進群交流學習