super的本质
super
关键字在调用方法的时候底层调用流程是怎样的?
我们通过一段代码来看一下super
底层实现,Person
类提供run
方法,Student
类继承自Person ,并重写run
方法,方法内部调用[super run];
,将Student.m
转化为c++
代码查看其底层实现。
// Student.m
- (void) run
{
[super run];
NSLog(@"Student...");
}
上述代码转化为c++代码
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___Student_e677aa_mi_0);
}
通过上述源码可以发现,[super run];
转化为底层源码内部其实调用的是objc_msgSendSuper
函数。
objc_msgSendSuper
函数内传递了两个参数。__rw_objc_super
结构体和sel_registerName("run")
方法名。
__rw_objc_super
结构体内传入的参数是self
和class_getSuperclass(objc_getClass("Student"))
也就是Student
的父类Person
首先我们找到objc_msgSendSuper
函数查看内部结构
id objc_msgSendSuper(struct objc_super * _Nonnull super, SEL _Nonnull op, ...)
可以发现objc_msgSendSuper
中传入的结构体是objc_super
,我们来到objc_super
内部查看其内部结构。
我们通过源码查找objc_super
结构体查看其内部结构。
// 精简后的objc_super结构体
struct objc_super {
__unsafe_unretained _Nonnull id receiver; // 消息接受者
__unsafe_unretained _Nonnull Class super_class; // 消息接受者的父类
/* super_class is the first class to search */
// 父类是第一个开始查找的类
};
从objc_super
结构体中可以发现receiver
消息接受者仍然为self
,superclass
仅仅是用来告知消息查找从哪一个类开始。从父类的类对象开始去查找。
我们通过一张图看一下其中的区别。
self/super调用方法的区别
从上图中我们知道super
调用方法的消息接受者receiver
仍然是self
,只是从父类的类对象开始去查找方法。
那么此时重新回到面试题,我们知道class的底层实现如下面代码所示
+ (Class)class {
return self;
}
- (Class)class {
return object_getClass(self);
}
class
内部实现是根据消息接受者返回其对应的类对象,最终会找到基类的方法列表中,而self
和super
的区别仅仅是self
从本类类对象开始查找方法,super
从父类类对象开始查找方法,因此最终得到的结果都是相同的。
另外我们在回到run
方法内部,很明显可以发现,如果super
不是从父类开始查找方法,从本类查找方法的话,就调用方法本身造成循环调用方法而crash。
同理superclass
底层实现同class
类似,其底层实现代码如下入所示
+ (Class)superclass {
return self->superclass;
}
- (Class)superclass {
return [self class]->superclass;
}
因此得到的结果也是相同的。
Self 和 Super的区别
Super是如何调用的?
[super message]的底层实现
1.消息接收者仍然是子类对象
2.从父类开始查找方法的实现
3.super:消息接收者仍然是当前类对象,只是从父类查找方法的实现
Super的本质?
super是一个编译器指示符
底层会转换为objc_msgSendSuper / objc_msgSendSuper2 函数的调用 , 暂时看不出来有什么区别 , 先知道会有2个吧
self和super区别?
self:是关键字
代表当前方法的调用者
如果是类方法:代表当前类
如果是对象方法:代表当前类的对象
super:编译器指示符,实际还是给self发的消息
[self message]和[super message]的实现区别?
查找方法的位置不一样,self是从当前类结构中开始查找,super是从父类中查找,但方法真正的接受者都是当前类或者当前类的对象
[self message]:
会转化为objc_msgSend(id self,SEL _cmd)这个函数,在当前类结构中找到方法并且调用
[super message]
会转化为id objc_msgSendSuper(struct __rw_objc_super *super, SEL op, …)