在平時(shí)的開發(fā)過程中敏晤,我們經(jīng)常會(huì)執(zhí)行[super xxx]
來調(diào)用父類的方法遵岩,但是我們很少會(huì)去關(guān)心super
關(guān)鍵字的底層是如何實(shí)現(xiàn)的集绰,接下來我們來看下super
關(guān)鍵字底層實(shí)現(xiàn)原理菠劝,我們新建一個(gè)工程赛糟,然后創(chuàng)建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
函數(shù):
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
Student *stu = [[Student alloc] init];
[stu run];
}
return 0;
}
接下來我們執(zhí)行命令xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 Student.m
將Student.m
文件轉(zhuǎn)換為底層c++文件版仔,轉(zhuǎn)換為底層的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
方法進(jìn)行簡化如下:
- (void)run {
[super run];
/**
結(jié)構(gòu)體objc_super包含兩個(gè)成員:
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__);
}
我們發(fā)現(xiàn)當(dāng)我們在run
函數(shù)中執(zhí)行[super run]
后,最終底層轉(zhuǎn)換為objc_msgSendSuper()
消息發(fā)送误墓,我們通過底層源碼看下objc_msgSendSuper
函數(shù)的定義蛮粮,查找路徑objc4 -> message.h -> objc_msgSendSuper
,具體底層函數(shù)定義如下:
/**
* 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
函數(shù)定義可以看到谜慌,函數(shù)接受兩個(gè)參數(shù)
- objc_super
- SEL
我們再來看下objc_super
結(jié)構(gòu)體底層定義如下:
/// 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
結(jié)構(gòu)體如下:
/**
從`objc_msgSendSuper`函數(shù)的注釋可以看到結(jié)構(gòu)體的兩個(gè)成員含義: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
底層定義然想,我們可以看到這個(gè)結(jié)構(gòu)體也包含兩個(gè)成員
- receiver
- super_class
我們通過objc_msgSendSuper
函數(shù)底層定義的注釋中可以查看到參數(shù)objc_super
結(jié)構(gòu)體中兩個(gè)成員的具體含義和作用
instance of the class that is to receive the message and the superclass at which to start searching for the method implementation
從上面注釋我們了解到receiver
就是消息的接受者(也就是方法調(diào)用者),superclass
就是指從父類開始查找方法
因此在Student
的init
初始化函數(shù)中打印結(jié)果如下:
- (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
函數(shù)的底層源碼實(shí)現(xiàn):
- (Class)class {
// self為方法調(diào)用者欣范,也就是消息接收者(receiver)变泄,返回當(dāng)前方法調(diào)用者的類對象
return object_getClass(self);
}
- (Class)superclass {
// self為方法調(diào)用者,也就是消息接收者(receiver)恼琼,返回當(dāng)前方法調(diào)用者的父類對象
return return self->superclass;
}
講解示例Demo地址:https://github.com/guangqiang-liu/07.2-RunTimeSuper
更多文章
- ReactNative開源項(xiàng)目OneM(1200+star):https://github.com/guangqiang-liu/OneM:歡迎小伙伴們 star
- iOS組件化開發(fā)實(shí)戰(zhàn)項(xiàng)目(500+star):https://github.com/guangqiang-liu/iOS-Component-Pro:歡迎小伙伴們 star
- 簡書主頁:包含多篇iOS和RN開發(fā)相關(guān)的技術(shù)文章http://www.reibang.com/u/023338566ca5 歡迎小伙伴們:多多關(guān)注妨蛹,點(diǎn)贊
- ReactNative QQ技術(shù)交流群(2000人):620792950 歡迎小伙伴進(jìn)群交流學(xué)習(xí)
- iOS QQ技術(shù)交流群:678441305 歡迎小伙伴進(jìn)群交流學(xué)習(xí)