每次听到“动态语言”就会思考一次这个问题,OC
为什么是动态语言?不同时期有不s同的理解。
最开始的理解是,在运行时才去调用特定的方法(OC
的消息转发机制属于动态性,并不是多态),编译时并不确定将来运行的时候调用什么方法。但是这个不就是面向对象的多态性吗?一般的面相对象的语言都会有多态性,例如java
,有多态性,但不是动态语言。
对于iOS
开发人员来说,除了OC
语言,其他的语言接触的很少,更不会深入理解,所以,不会有两种语言的对比,对于其他语言的了解,也只是了解一点皮毛,包括我。这个是搞iOS
,或只搞一个平台带来的弊病。所以,如果只专注在一个平台,更具体点,专注于一种语言,那么,对很多概念是无法理解的。
在我们需要具备其他一门语言的时候,swift
来了,恰巧swift
又是一个静态语言,这样,我们iOS
开发者,可以同时理解动态语言和静态语言了。
百度百科里关于动态语言的定义
动态语言,是指程序在运行时可以改变其结构:新的函数可以被引进,已有的函数可以被删除等在结构上的变化,类型的检查是在运行时做的,优点为方便阅读,清晰明了,缺点为不方便调试。
也就是,在程序运行后,还可以添加新的函数,或者删除已有的函数,或者添加新的属性,或者删除已有的属性,总之,就是可以修改你之前写好的代码。例如,我定义了一个Person
类,代码里只写了一个属性name
,但是,我可以在别的地方做些操作(写些代码),给这个Person
类,添加一个age
属性,加一个eat
方法等等。
我们做的操作是什么呢?其实就相当于你改了Person
类的代码,加上了age
属性,加上了eat
方法。
也就是定义里说的,
动态语言,是指程序在运行时可以改变其结构。
我们把原本只有一个name属性的Person类改的面目全非了。
我们都知道,我们怎么办到添加属性和方法呢?这个就是我们iOS
开发者非常熟悉的runtime
。所以,我们说,OC
的动态性是runtime
支持的。没有runtime
,就不具备在运行时修改代码的能力。
runtime
的确是个伟大的特性,长久以来都是iOS
程序员引以为傲的,但是swift
却去掉了动态性,原生并不支持runtime
。runtime
的特性在很多场景下都是最佳的解决方案,所以,swift
没有runtime
特性,的确让人很不舒服。
swift
可以通过兼容OC
来使用runtime
特性,但始终不是swift
的特性。
runtime
特性的确有很多的弊端,例如执行速度上,肯定是静态语言更快。但是动态语言优点又显然超过了弊端,所以,在不久的将来swift
一定会加入runtime
特性,当然,到时可能有一个新名字,未必还是叫runtime
。
runtime
在这里我们可以看作一个库,像其他库一样,这个库提供了一些API
,让我们来实现添加方法,删除方法,交换方法等等。这个库真正做了什么呢?是不是真的在运行的时候去把我们写好的代码改掉呢?例如添加一个方法,是不是真的在我们的代码下面再写一个我们添加的方法呢?我们知道另外一件事,就是ARC
的实现机制,ARC并不是垃圾回收机制,而是,在编译的时候,系统真的会给我们加上代码(release
,retain
,autorelease
等)。那runtime
是不是呢?显然不是,runtime
是在运行的时候起作用的,那个时候,代码已经完成了编译,怎么还能改代码呢?所以,真正的改代码只能发生在编译前,编译之后就没有办法改代码了。
我们知道,OC
里有很多库都是C/C++
实现的,包括runtime
库,为什么是C/C++
实现?因为所有的OC
在编译之前都会转为C/C++
代码,也就是,OC
不过是在C/C++
基础上实现的一个语言,瞬间不那么高大上了。
OC
里的类,数组,各种结构,各种逻辑,最终都是C\C++
实现。例如,我们要在OC
类里添加一个方法。在C++
层面是,OC
方法会转为函数指针,有一个数组存放这些函数指针,添加一个方法就是在这个数组里,再添加一个函数指针。在OC
看来,你给这个类添加了一个方法。在C++
看来,你不过是在数组里添加了一个元素,并没有什么奇怪的。