当前位置: 首页 > news >正文

《Effective Objective-C 2.0 》 阅读笔记 item11

第11条:理解objc_msgSend的作用

1. 动态语言特性

在Objective-C中,如果向某对象传递消息,那就会使用动态绑定机制来决定需要调用的方法。在底层,所有方法都是普通的C语言函数,然而对象收到消息之后,究竟该调用哪个方法则完全于运行期决定,甚至可以在程序运行时改变,这些特性使得Objective-C成为一门真正的动态语言。

2. 消息派发(message dispatch)

*** 消息派发的一般过程 ***
给对象发送消息,如下:

id returnValue  = [someObject messageName:parameter];

解释:someObject是“接收者”,messageName是“选择器”,选择器与参数合起来成为“消息”。

编译器在看到此消息后,将其转换为一条标准的C语言函数调用objc_msgSend,其原型如下:

void objc_msgSend(id self, SEL cmd, ...)

 解释:这是个参数可变的函数。第一个参数代表接收者,第二个参数代表选择器,后续参数就是消息中的那些参数,其顺序不变。

对先前例子中的消息进行转换,如下:

id returnValue  = objc_msgSend(someObject, @selector(messageName:), parameter);

解释:objc_msgSend函数会依据接收者与选择器的类型来调用适当的方法。为了完成此操作,该方法需要在接收者所属的类中搜寻其“方法列表”,如果能找到与选择器名称相符的方法,就跳至其实现代码。若是找不到,那就沿着继承体系继续向上查找,等找到合适的方法之后再跳转。如果最终还是找不到相符的方法,那就执行“消息转发”(message forwarding)操作。

3. 消息派发的特殊情况

  • objc_msgSend_stret:如果待发送的消息要返回结构体,那么可交由此函数处理。
  • objc_msgSend_fpret:如果消息返回的是浮点数,那么交由此函数处理。
  • objc_msgSendSuper:如果要给超类发消息,例如[super message:parameter],那么就交由此函数处理。

4. 尾调用优化

objc_msgSend等函数一旦找到应该调用的方法实现之后,就会“跳转过去”。之所以能这么做,是因为Objective-C对象的每个方法都可以视为简单的C函数,其原型如下;

<return_type> Class_selector(id self, SEL _cmd, ...)

 

解释:每个类里都有一张表格,其中的指针都会指向这种函数,而选择器的名称则是查表时所用的“键”。objc_msgSend等函数正是通过这张表格来寻找应该执行的方法并跳至其实现的。其中,所使用的“尾调用优化”(tail-call optimization)技术,可以让“跳至方法实现”这一操作变得更简单些。但是,只有当某函数的最后一个操作仅仅是调用其他函数而不会将其返回值另作他用时,才能执行“尾调用优化”。

要点

  • 消息由接收者选择器参数构成。给某对象“发送消息”(invoke a message)也就相当于在该对象上“调用方法”(call a method)。
  • 发给某对象的全部信息都要由“动态消息派发系统”(dynamic message dispatch system)来处理,该系统会查出对应的方法,并执行其代码。

http://www.lryc.cn/news/56324.html

相关文章:

  • Python常见装饰器使用(实用向)
  • 集合详解之(三)单列集合接口Set及具体子类HashSet、TreeSet
  • 力扣刷题笔记22—— 矩阵中的路径(回溯)/pair的学习
  • Spring学习1
  • Keep再闯IPO,三年亏损16亿,会员留存率跌破70%
  • 软件测试分类详解
  • 网站怎么优化出排名
  • h5|web页面嵌套iframe传参给cocosCreator
  • 阿里云安全产品Web应用防火墙是什么?有什么作用?
  • 【SSM】Spring6(九.代理模式)
  • 【1017. 负二进制转换】
  • C语言实现插入排序与希尔排序
  • 第九章-DOM与CSS
  • 蓝桥杯真题练习
  • 插入排序的简单理解
  • Springboot框架集成Websocket通信方式
  • 将json数据分组
  • 从零开始实现一个C++高性能服务器框架----Socket模块
  • ld: library not found for -lcrt0.o
  • 接口测试和功能测试的区别有哪些?说一些你不知道的知识
  • 深度学习实战——不同方式的模型部署(CNN、Yolo)
  • 【论文阅读】GNN阅读笔记
  • QT常用控件——QTreeWidget(树控件),QTableWidget控件
  • 为什么学校购买小型数控机床而不是大型工业数控机床?
  • 【Go自学】一文搞懂Go append方法
  • 【压测】通过Jemeter进行压力测试(超详细)
  • C# | 上位机开发新手指南(七)加密算法
  • 实验一 跨VLAN访问
  • 通信算法之130:软件无线电-接收机架构
  • C++编程大师之路:从入门到精通-C++基础入门