self和super的区别

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结构体内传入的参数是selfclass_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消息接受者仍然为selfsuperclass仅仅是用来告知消息查找从哪一个类开始。从父类的类对象开始去查找。

我们通过一张图看一下其中的区别。

self/super调用方法的区别

从上图中我们知道
super调用方法的消息接受者receiver仍然是self,只是从父类的类对象开始去查找方法。

那么此时重新回到面试题,我们知道class的底层实现如下面代码所示

+ (Class)class {
    return self;
}

- (Class)class {
    return object_getClass(self);
}

class内部实现是根据消息接受者返回其对应的类对象,最终会找到基类的方法列表中,而selfsuper的区别仅仅是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, …)



链接:https://www.jianshu.com/p/57e3f555756e
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值