iOS 开发中经常用到或者看到 [self class]
和 [super class]
,很多人都会用但是没有研究过这两者究竟有什么区别,今天就本文就讲解一下 self
和 super
两者的区别
self 和 super 的区别
self
是一个隐藏参数变量,指向当前调用方法的对象,还有一个隐藏参数是 _cmd,代表当前方法 selector
,在 runtime 时会调用 objc_msgSend()
方法
super
并不是隐藏参数,它只是编译器的指令符号,它和 self
指向的是相同的消息接收者,在 runtime 时调用 objc_msgSendSuper()
方法
官方文档里面 self 和 super 的解释:
Whenever you’re writing a method implementation, you have access to an important hidden value, self. Conceptually, self is a way to refer to “the object that’s received this message.” It’s a pointer, just like the greeting value above, and can be used to call a method on the current receiving object.
There’s anotherimportant keyword available to you in Objective-C, called super. Sending a message to super is a way to call through to a method implementation defined by a superclass further up the inheritance chain. The most common use of super is when overriding a method.
接下来我们先看看下面的代码,代码里定义了一个 Parents 的父类,定义了一个 继承自 Parents 的子类 Children,在 Parents 的 .h 文件里定一个了一个 eat
方法,在 Children 的 .m 文件里重写了父类的eat
方法
Parents 类的实现:
|
|
Children 类的实现:
|
|
然后在控制器里实例化一个 Children 对象并调用 eat
方法
|
|
得到下面的打印结果:
|
|
解释一下打印结果:
[self class]
: 的调用者是 Children
[self superclass]
: self
的父类是 Parents
[super class]
: 当前调用者还是 self
也就是 Children
,只不过有 super
之后编译器会去调用父类的 class
方法,而不是本类里的[super superclass]
:当前调用者是 self
也就是 Children
,它的 superclass
是 Parents
,只不过有 super
之后编译器会去调用父类的 superclass
方法,而不是本类里的
self 和 super 底层的实现原理
OC 的内部实现是运行时(Runtime)机制,方法的调用实际上消息发送机制(msgSend),先看一下 objc_msgSend()
的函数定义:
|
|
这个方法的第一个参数是消息接收者,第二个参数是调用的具体类方法的 selector,后面是 selector 方法的可变参数,先不管这个可变参数
以上面 [self methonName]
为例,编译器会替换成下面的代码:
|
|
这个 selector 是从当前 self 的方法列表开始找,当找到后把对应的 selector 传递过去
而当使用 [super methonName]
调用时,会使用objc_msgSendSuper()
函数,编译器会替换成下面的代码:
|
|
看一下 objc_msgSendSuper()
的函数定义:
|
|
第一个参数是个 objc_super
的结构体,第二个参数还是类似上面的类方法的 selector
,先看下 objc_super
这个结构体的组成:
|
|
这个结构体包含了两个成员,一个是 receiver
,这个类似上面 objc_msgSend
的第一个参数,第二个成员是记录这个类的父类是什么
以上面的 [super methonName]
为例,当编译器遇到 Children 里的方法里的 [super methonName]
时,开始做这几个事:
- 构建
objc_super
的结构体,此时这个结构体的第一个成员变量receiver 就是Children
,和self
相同,而第二个成员变量super_Class
就是指类Parents
,因为Children
的父类就是Parents
- 调用
objc_msgSendSuper()
的方法,将第一步构建的这个结构体和 methonName 的 selector 传递过去,函数里面在做的事情类似这样:从objc_super
结构体指向的super_Class
的方法列表开始找 methonName 的 selector,找到后再以objc_super->receiver
去调用这个 selector,可能也会使用objc_msgSend()
这个函数,不过此时的第一个参数就是objc_super->receiver
,第二个参数是从objc_super->super_Class
中找到的 selector
里面的调用机制大体就是这样了,通过以上面的分析,回过头来看开始的代码,当输出 [self class]
和 [super class]
时,是个怎样的过程:
当调用 [self class]
时,这时的 self
是 Children
,在使用objc_msgSend()
时,第一个参数是 self
,也是 Children *child
这个实例,第二个参数,要先找到 class
这个方法的selector,先从 Children
这个类开始找,没有找到,然后到Children
的父类 Parents
中去找,也没有,再去 Parents
的父类 NSObject
去找,一层一层向上找之后,在 NSObject
的类中发现这个 class
方法,而 NSObject
的这个 class
方法的返回值就是 self
的类别,所以这里打印 Children
当使用 [super class]
时,这时要转换成objc_msgSendSuper()
的方法,先构造 objc_super
的结构体,第一个成员变量就是 self
, 第二个成员变量是 Parents
,然后要找 class
这个 selector,先去 super_Class
也就是 Parents
中去找,没有,然后去 Parents
的父类中去找,结果还是在 NSObject
中找到了,然后内部使用函数 objc_msgSend(objc_super->receiver, @selector(class))
去调用,此时已经和我们用 [self class]
调用时相同了,此时的 receiver
就是 Children *child
这个实例,所以这里返回的也是 Children
以上就是在 OC 中的类实现中经常看到这两个关键字 self
和 super
的区别
参考文章:
iOS经典讲解之[self class]和[super class]的区别
本人刚开始写博客,主要是为了给自己的知识点做一个笔记,方便自己以后查阅,如果能让别人有所启发也是荣幸之至!如有错误,欢迎指正!