Objective-C 的 self 和 super 详解 (用简单程序说明问题)
|
在 Objective-C 中的类实现中经常看到这两个关键字 ”self” 和 ”super”,以以前 oop 语言的经验,拿 c++ 为例,self 相当于 this,super 相当于调用父类的方法,这么看起来是很容易理解的。以下面的代码为例:
复制代码 上面有简单的两个类,在子类PersonMe中调用了自己类中的setAge和父类中的setName,这些代码看起来很好理解,没什么问题。
复制代码 这样在调用时,会打出来这两个的class,先猜下吧,会打印出什么?按照以前oop语言的经验,这里应该会输出:
但是编译运行后,可以发现结果是:
self 的 class 和预想的一样,怎么 super 的 class 也是 PersonMe? 真相 self 是类的隐藏的参数,指向当前当前调用方法的类,另一个隐藏参数是 _cmd,代表当前类方法的 selector。这里只关注这个 self。super 是个啥?super 并不是隐藏的参数,它只是一个“编译器指示符”,它和 self 指向的是相同的消息接收者,拿上面的代码为例,不论是用 [self setName] 还是 [super setName],接收“setName”这个消息的接收者都是 PersonMe* 当使用 self 调用方法时,会从当前类的方法列表中开始找,如果没有,就从父类中再找;而当使用 super 时,则从父类的方法列表中开始找。然后调用父类的这个方法 One more step 这种机制到底底层是如何实现的?其实当调用类方法的时候,编译器会将方法调用转成一个 C 函数方法调用,Apple 的 objcRuntimeRef 上说:
可以看到会转成调用上面 4 个方法中的一个,由于 _stret 系列的和没有 _stret 的那两个类似,先只关注 objc_msgSend 和 objc_msgSendSuper 两个方法。当使用 [self setName] 调用时,会使用 objc_msgSend 的函数,先看下 objc_msgSend 的函数定义:
复制代码 第一个参数是消息接收者,第二个参数是调用的具体类方法的 selector,后面是 selector 方法的可变参数。我们先不管这个可变参数,以 [self setName:] 为例,编译器会替换成调用 objc_msgSend 的函数调用,其中 theReceiver 是 self,theSelector 是 @selector(setName),这个 selector 是从当前 self 的 class 的方法列表开始找的 setName,当找到后把对应的 selector 传递过去。 而当使用 [super setName] 调用时,会使用 objc_msgSendSuper 函数,看下 objc_msgSendSuper 的函数定义:
复制代码 第一个参数是个objc_super的结构体,第二个参数还是类似上面的类方法的selector,先看下objc_super这个结构体是什么东西:
复制代码 可以看到这个结构体包含了两个成员,一个是 receiver,这个类似上面 objc_msgSend 的第一个参数 receiver,第二个成员是记录写 super 这个类的父类是什么,拿上面的代码为例,当编译器遇到 PersonMe 里 setName:andAge 方法里的 [super setName:] 时,开始做这几个事:
里面的调用机制大体就是这样了,以上面的分析,回过头来看开始的代码,当输出 [self class] 和 [super class] 时,是个怎样的过程。 当使用 [self class] 时,这时的 self 是 PersonMe,在使用 objc_msgSend 时,第一个参数是 receiver 也就是 self,也是 PersonMe* me 这个实例。第二个参数,要先找到 class 这个方法的 selector,先从 PersonMe 这个类开始找,没有,然后到 PersonMe 的父类 Person 中去找,也没有,再去 Person 的父类 NSObject 去找,一层一层向上找之后,在 NSObject 的类中发现这个 当使用 [super class] 时,这时要转换成 objc_msgSendSuper 的方法。先构造 objc_super 的结构体吧,第一个成员变量就是 self,第二个成员变量是 Person,然后要找 class 这个 selector,先去 superClass 也就是 Person 中去找,没有,然后去 Person 的父类中去找,结果还是在 NSObject 中找到了。然后内部使用函数 objc_msgSend(objc_super->receiver, @selector(class)) 去调用,此时已经和我们用 |
Objective-C 的 self 和 super 详解 (用简单程序说明问题)的更多相关文章
- Objective-C中 Self和 Super详解
Objective-C中 Self和 Super详解 Objective-C 中Self 和 Super 详解本文要介绍的内容,在 Objective-C 中的类实现中经常看到这两个关键字 self ...
- 第十一章、super()详解
目录 第十一章.super()详解 一.引出super()来由 第十一章.super()详解 一.引出super()来由 原始用法: 在python类的方法中,要调用父类的某个方法,通常是类.方法() ...
- [强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!)
原文:[强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!) [强烈推荐]ORACLE PL/SQL编程详解之七: 程序包的创建与应用(聪明在于学习,天 ...
- JSP 注释的详解及简单实例
转自:https://www.jb51.net/article/124727.htm JSP 注释的详解及简单实例 一 三种格式 二 举例 ? 1 2 3 4 5 6 7 8 9 10 11 12 1 ...
- 详解微信小程序开发(项目从零开始)
一.序 微信小程序,估计大家都不陌生,现在应用场景特别多.今天就系统的介绍一下小程序开发.注意,这里只从项目代码上做解析,不涉及小程序如何申请.打包.发布的东西.(这些跟着微信官方文档的流程走就好). ...
- [svc]tomcat配置文件详解-最简单的基于mvn的war包
tomcat安全管理规范 java&tomcat配置参考(多看看这位大牛的博客,写的很好) Tomcat系列之Java技术详解 http://blog.51cto.com/freeloda/1 ...
- Spring AOP详解及简单应用
Spring AOP详解 一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址: ...
- Android清单文件详解(三)----应用程序的根节点<application>
<application>节点是AndroidManifest.xml文件中必须持有的一个节点,它包含在<manifest>节点下.通过<application>节 ...
- Python中super详解
转至:https://mozillazg.com/2016/12/python-super-is-not-as-simple-as-you-thought.html 说到 super, 大家可能觉得很 ...
随机推荐
- inline,block,inline-block解析
display:block就是将元素显示为块级元素. block元素的特点是: 总是在新行上开始: 高度,行高以及顶和底边距都可控制: 宽度缺省是它的容器的100%,除非设定一个宽度 <div& ...
- L130
Trump Administration Backs Asian-Americans in Harvard CaseThe United States Justice Department on Th ...
- 机器学习(九)—FP-growth算法
本来老师是想让我学Hadoop的,也装了Ubuntu,配置了Hadoop,一时间却不知从何学起,加之自己还是想先看点自己喜欢的算法,学习Hadoop也就暂且搁置了,不过还是想问一下园子里的朋友有什么学 ...
- Sphinx 匹配模式
所谓匹配模式就是用户如何根据关键字在索引库中查找相关的记录. SPH_MATCH_ALL, 匹配所有查询分词(默认模式); 如“手机配件”,不匹配 “我有一部手机”,但可以匹配 “手机坏了,需要找配件 ...
- tensorflow中常用激活函数和损失函数
激活函数 各激活函数曲线对比 常用激活函数: tf.sigmoid() tf.tanh() tf.nn.relu() tf.nn.softplus() tf.nn.softmax() tf.nn.dr ...
- SpringMVC使用session实现简单登录
1.首先为了能直观地在jsp页面体现session的内容,我使用了jstl表达式,首先在pom.xml中引入jstl的依赖 <!-- jstl所需要的依赖 --> <dependen ...
- Python笔记-3
一.文件的操作 1.文件的读.写.新增 读文件的获取句柄的语法:f=open('path/file') 句柄的理解: <_io.TextIOWrapper name='/root/myfile/ ...
- [Luogu4390][BOI2007]Mokia 摩基亚
luogu 题意 支持平面内单点加一个值以及矩阵求和. 平面大小\(W\le2*10^6\),修改操作\(\le1.6*10^5\),查询操作\(\le10^4\) sol \(CDQ\)写一发. 把 ...
- Tornado服务端基本的配置文件(Python)
web_set = { # -------一般设置-------- 'debug': True, 'port': 8836, 'autoreload': True, 'ui_modules': {}, ...
- as3 htmlText 的bug
as的文本框 会把连续的英文当作一个单词处理 如果是在已有内容的行后 超过宽度就会换行 左边的用了英文冒号直接被当成完整的单词右边的被当成了 jj5jk : mmmmmmmmmm 三个单词