在对象上调用方法,术语叫作“传递消息”,消息有“名称”和“选择器(方法)”,能够接收参数,还可能有返回值。OC是C的超集,C语言使用静态绑定,在编译期间就能决定运行时作调用的函数。缓存
#include <stdio.h> void printHello() { printf("hello, world!\n"); } void printGoodbye() { printf("Goodbye, world!\n"); } void doTheThing(int type) { if (type == 0) { printHello(); } else { printGoodbye(); } }
#include <stdio.h> void printHello() { printf("hello, world!\n"); } void printGoodbye() { printf("Goodbye, world!\n"); } void doTheThing(int type) { void (*fnc)(); if (type == 0) { fnc = printHello; } else { fnc = printGoodbye; } fnc(); }
给对象发送消息能够这么写:函数
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 会在接受者所属的类中搜寻其“方法列表”,若是找到与“选择器”名称相符的代码就实现,没找到就延继承体系向上查找,最终找不到,就实现“消息转发”。
备注:每一个类都有一块缓存“快速映射表”,若是稍后还向该类发送相同的消息,执行就快。优化
运行环境中一些“边界状况”,须要其余函数处理
1.objc_msgSend_stret:若是待发送的消息要返回结构体,交给这个函数。
2.objc_msgSend_fpre:若是消息返回的是浮点数,交给这个函数。
3.objc_msgSendSuper:给超类发消息,用这个函数。也有与objc_msgSend_fpre和objc_msgSend_fpre等效的处理超类消息的方法。
编码
OC对象的每一个方法均可以看作简单的C函数,原型以下:
指针
<return_type> Class_selector(id self, SEL _cmd, ...)每一个类里都会有一张表格,其中的指针都会指向这种函数,选择器的名称则是查表时用的“键”,objc_msgSend用这张表来寻找应该执行的方法并跳转实现。
“尾调用优化”:若是函数的最后一项操做是调用另一个函数,编译器会生成调转至另外一个函数所用的指令码。不会向调用堆栈中推入新的“栈帧”。
注意:只有当函数的最后一项操做仅仅是调用其余函数而不会将其返回值另作他用时
code