学习OC一般都知道它是一门动态语言,但是一开始会很难理解什么是动态,这里我会用尽量简洁明了的语言说明我的理解
动态绑定
如果了解过C语言调用函数的原理,那么动态绑定也不会很难理解,C语言采用的是静态绑定
举个例子:
#import <stdio.h>
void printHello(){
printf("hello world");
}
void printGoodbye(){
printf("goodbye world");
}
int main(){
int type;
scanf("%d",&type);
if(type==0)
printHello();
else
printGoodbye();
return 0;
}
我们知道,程序运行需要先编译,静态绑定就是指程序在编译的时候就已经确认好了要调用哪个函数,在汇编语言中,调用一个函数大概格式是
指令+函数地址
也就是说你看上面那段代码,每一行都能编译成确定汇编语言,前面两个函数的地址已经确认,对于计算机来说每一行都已经跟他确认好了他应该去哪个地方调用函数
如果觉得不好理解我们可以这样想,你现在有一个任务清单:
超市地址:
xxx-xxx-xxx
公司地址:
xxx-xxx-xxx
你的任务:
1.如果今天下雨,那么去超市买牛奶
2.如果今天不下雨,那么去公司工作
你在分析你的任务清单的时候,你就知道怎么去执行任务了,就算你不知道今天是不是下雨,但是你知道你要去的地方的地址,这就是静态绑定
动态绑定
同样我们来看一个例子:
#import <stdio.h>
void printHello(){
printf("hello world");
}
void printGoodbye(){
printf("goodbye world");
}
int main(){
void (*fnc)();
int type;
scanf("%d",&type);
if(type==0)
fnc=printHello;
else
fnc=printGoodbye;
fnc();
return 0;
}
对于fnc这个函数,我们只有在执行时才知道它的地址到底在哪,因为你在编译fnc()
这句话的时候,你并不能确定fnc地址
下面是形象化的分析
公园地址:
xxx-xxx-xxx
公司地址:
xxx-xxx-xxx
目的地
1.如果今天下雨,那么目的地是公司
2.如果今天不下雨,那么目的地是公园
你的任务:
今天去目的地
你在分析你的任务的时候,今天去目的地
,你不能确定你的 目的地 地址到底在哪,除非你知道今天下不下雨
所以如果对于计算机来说只有在运行时的时候才能确认去调用哪个方法,那么就叫做动态绑定,绑定可以认为是调用函数的过程
OC消息机制
介绍这个是为了更好的了解OC调用函数的机制
OC调用函数采用的是消息的机制,如:
[obeject printHello];
obeject叫做接受者
,printHello叫做选择子(selector)
,也就是说方法名就是选择子,如果这个方法还有参数,那么参数和选择子一起就叫做消息
在调用函数的时候,obejct收到一条消息,然后根据消息的信息动态地去寻找方法,也就是说,本身在编译的时候,这个方法的调用是没有确定的,只是编译成类似这样意思的语句
"hey obeject !我现在发条消息给你 待会你自己在运行的时候再去找这个方法吧"
在整个过程中有两个部分很重要:
接受者有一个方法表,一个表用来记录它所有的方法地址,然后根据消息去这个方法表里面搜索相应的方法
objc_msgSend方法,这个方法就是核心函数,用来将刚刚的消息发送给接受者(这个地方就不做深入的介绍了)
再补充一点,OC动态绑定的效率有时候很高,因为他在搜索的方法是根据一个整数ID寻找的,而且是散列表,但是对于C来说使用的是根据字符串查找的(来源:http://www.cnblogs.com/dxb123456/p/5525343.html)
动态类型
正如字面的意思,就是在运行时才确定的类型
对于int等其他类型,一般在编译的时候就已经确定了这个类型,
而OC中的动态类型
<font color=red>id</font> 是不确定的类型
特点:
- 动态类型调用不是所期待的方法时,在编译时不会报错,但是在运行时会崩溃,但是静态类型在编译的时候就会报错
- 在把id类型赋值给特定类型比如
graphic
时,并没有类型的转换(假设原来id就是graphic生成的),只不过是因为执行环境能辨认出此时id代表的是哪个类型
应用场景:
多态 比如函数要根据情况来返回不同的值,就可以使用id
参考:
https://blog.csdn.net/vivo_x9/article/details/82721181
https://www.xuebuyuan.com/3187502.html
https://droidyue.com/blog/2014/12/28/static-biding-and-dynamic-binding-in-java/