runtime - 面试题系列1 - Super
1.Super
-
@interface Person : NSObject
-
@end
-
-
@interface Student : Person
-
@end
-
@implementation Student
-
-
-(instancetype)init
-
{
-
if (self = [super init]) {
-
NSLog(@"%@",[self class]);
-
NSLog(@"%@",[super class]);
-
NSLog(@"%@",[self superclass]);
-
NSLog(@"%@",[super superclass]);
-
}
-
return self;
-
}
-
@end
面试题是:上面这段代码,最终会输出什么
正常人应该会觉得[self class]肯定是输出student,[super class]肯定是Person,[self superclass]是Person,[super superclass]是NSObject
实际答案:Student,Student,Person,Person
原理:Super关键字到底做了什么,转c 就知道它底层干了啥
先cd到main.m的文件夹 xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m
输入这段,之后就转成了main.cpp
-
static instancetype _I_Student_init(Student * self, SEL _cmd) {
-
if (self = ((Student *(*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))}, sel_registerName("init"))) {
-
NSLog((NSString *)&__NSConstantStringImpl__var_folders_td_r9wqf72n79db8c30dyg3pwsc0000gn_T_main_55b348_mi_0,((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class")));
-
NSLog((NSString *)&__NSConstantStringImpl__var_folders_td_r9wqf72n79db8c30dyg3pwsc0000gn_T_main_55b348_mi_1,((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))}, sel_registerName("class")));
-
NSLog((NSString *)&__NSConstantStringImpl__var_folders_td_r9wqf72n79db8c30dyg3pwsc0000gn_T_main_55b348_mi_2,((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("superclass")));
-
NSLog((NSString *)&__NSConstantStringImpl__var_folders_td_r9wqf72n79db8c30dyg3pwsc0000gn_T_main_55b348_mi_3,((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))}, sel_registerName("superclass")));
-
}
-
return self;
-
}
代码很多,大部分都是内部操作,和一些转译操作什么的,核心的只有这一个函数,是初始化函数,把NSLog去掉,然后再简化一下
-
((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class"));
-
((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))}, sel_registerName("class")));
-
((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("superclass")));
-
((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))};
然后可以看出superClass会调用SuperClass函数,而super关键字会调用 objc_msgSenderSuper这个函数,然后传入父类,问题就在于 superClass 和objc_msgSenderSuper做了些啥
-
/**
-
* 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);
-
这个函数目前我没看到开源代码,只找到了对应的解释,传入的是一个结构体,和一个函数,函数就是调用的那个比如[super class],那么这个函数就是class,根据调用不同这个函数也不同,然后是结构体
-
struct objc_super {
-
/// Specifies an instance of a class.
-
__unsafe_unretained _Nonnull id receiver;
-
-
/// Specifies the particular superclass of the instance to message.
-
-
/* For compatibility with old objc-runtime.h header */
-
__unsafe_unretained _Nonnull Class class;
-
-
__unsafe_unretained _Nonnull Class super_class;
-
-
/* super_class is the first class to search */
-
};
这里就是结构体的定义,是一个接受者和一个接受者的父类,这个结构体就是,一个类和他的父类,这里的解释很清楚从父类搜索它的方法实现,本身调用者还是类本身,而返回值是返回的方法调用者,所以用了super 和不用super只是寻找这个方法的本身位置不一样,并不会影响返回值
************补充**************
上面superclass这个函数的源码,就是返回一个父类
-
- (Class)superclass {
-
return [self class]->superclass;
-
}
所以上述代码里面打印出父类的,只有调用了superclass函数的代码
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgabaje
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13