欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OC语言的动态性

程序员文章站 2024-01-14 21:02:58
...
概念

Objective-C 是面相运行时的语言,它会尽可能的把编译和链接时要执行的逻辑延迟到运行时。使用Runtime可以按需要把消息重定向给合适的对象,交换方法的实现等等。

Runtime简称运行时,其中最主要的是消息机制,是一个主要使用 C 和汇编写的库,为 C 添加了面相对象的能力并创造了 Objective-C。。OC的函数调用称为消息发送。属于动态调用过程。在编译的时候并不能决定真正调用哪个函数(在编 译阶段,OC可以调用任何函数,即使这个函数并未实现,只要声明过就不会报错。而C语言在编译阶段就会报错)。只有在真正运行的时候才会根据函数的名称找 到对应的函数来调用。

消息的传递
[obj makeText];
==》
objc_msgSend(obj,@selector(makeText));

编译器执行上述转换。在objc_msgSend函数中,首先通过obj的isa指针找到obj对应的class。每个对象内部都默认有一个isa指针指向这个对象所使用的类。isa是对象中的隐藏指针,指向创建这个对象的类。在Class中先去cache中通过SEL查找对应函数method(cache中method列表是以SEL为key通过hash表来存储的,这样能提高函数查找速度),若cache中未找到,再去methodList中查找,若methodlist中未找到,则取superClass中查找。若能找到,则将method加入到cache中,以方便下次查找,并通过method中的函数指针跳转到对应的函数中去执行。

动态的体现

OC的动态特性表现为了三个方面:动态类型、动态绑定、动态加载。之所以叫做动态,是因为必须到运行时(runtime)才会做一些事情。

  • 动态类型
    就是id类型。动态类型是跟静态类型相对的。内置的基本类型都属于静态类型(int、NSString等)。静态类型在编译的时候就能被识别出来(即前面说的静态输入)。所以,若程序发生了类型不对应,编译器就会发出警告。而动态类型就编译器编译的时候是不能被识别的,要等到运行时(runtime),即程序运行的时候才会根据语境来识别。所以这里面就有两个概念要分清:编译时跟运行时。

动态语言和静态语言的一个区别是静态语言提前编译好文件,即所有的逻辑已在编译时确定,运行时直接加载编译后的文件;而动态语言是在运行时才确定实现。典型的静态语言是C++,动态语言包括OC,JAVA,C#等;因为静态语言提前编译好了执行文件,也就是通常所说的静态语言效率较高的原因

  • 动态绑定
    dynamic binding,需要用到@selector/SEL。先来看看“函数”,对于其他一些静态语言,比如c++,一般在编译的时候就已经将要调用的函数的函数签名都告诉编译器了。静态的,不能改变。而在OC中,其实是没有函数的概念的,我们叫“消息机制”,所谓的函数调用就是给对象发送一条消息。这时,动态绑定的特性就来了。OC可以先跳过编译,到运行的时候才动态地添加函数调用,在运行时才决定要调用什么方法,需要传什么参数进去,这就是动态绑定。要实现他就必须用SEL变量绑定一个方法。最终形成的这个SEL变量就代表一个方法的引用。这里要注意一点:SEL并不是C里面的函数指针,虽然很像,但真心不是函数指针。SEL变量只是一个整数,他是该方法的ID。以前的函数调用,是根据函数名,也就是字符串去查找函数体。但现在,我们是根据一个ID整数来查找方法,整数的查找自然要比字符串的查找快得多!所以,动态绑定的特定不仅方便,而且效率更高。
  • 动态加载
    就是根据需求动态地加载资源,在运行时加载新类。在运行时创建一个新类,只需要3步:

1、为 class pair分配存储空间 ,使用 objc_allocateClassPair函数 2、增加需要的方法使用class_addMethod函数,增加实例变量用class_addIvar 3 、用objc_registerClassPair函数注册这个类,以便它能被别人使用。