1

给你 C 语言,如何实现一个 Objective-C?

一个OC的编程者的内功有多深厚,就是要看编程者能把 “给你 C 语言,如何实现一个 Objective-C?” 这个问题答到什么程度。是的OC就是C的超集,而这是为何,则要牵扯到一个历史悠久的语言SmalkTalk.

Smalltalk 是世界上第二个面向对象的语言。(很可惜由于编译速度慢的原因,它最后还是被抛弃),然而它的思想则对之后的编程语言有着超前的指导作用。

  1. 基本思想一:完全的面向对象。万事万物都是对象,比Java还要彻底的面向对象,包括数据常量也是对象。

  2. 基本思想二:一切行为(也就是java中的方法),不再理解为方法调用,而是理解为向一个对象发送消息,也就是向一个对象发送一条命令,这个消息命令也可以带参数。
    而OC 的发明者 Brad Cox 和 Tom Love 在当时主流且高效的 C 语言基础上,借鉴 Smalltalk 这两个思想想要搞出一个易用且轻量的 C 语言扩展,但 C 和 Smalltalk 的思想和语法格格不入,比如在 Smalltalk 中一切皆对象,一切调用都是发消息:

233 log

再比如用一个工厂方法来实例化一个对象:

p := Person name: 'sunnyxx' age: 26

在当时来看,一个具有面向对象功能的 C 语言真的是非常有吸引力,但必须得解决消息语法的转换,于是乎他们开发了一个 Preprocessor,去解析 Smalltalk 风格的语法,再转换成 C 语言的代码,进而和其他 C 代码一起编译。这个过程和现在 JavaScript 里的 CoffeeScript、JSX 很相似,构建一个 DSL,用转化器转化成原始语言的代码。

然而现在问题来了, Smalltalk 语法里面又是空格、又是冒号的,万一遇到个什么复杂嵌套调用,语法解析多难写呀,于是乎他们想,既然什么花括号 大括号都有了,那只好把消息两边加个中括号吧 ,这样 Parser 写起来简单多了呢对吧:

[Person name:"sunnyxx" age: 26];

这就造就了 Objective-C 奇怪的中括号、冒号四不像语法,这怎么看都是个临时的方案,但在当时可能是唯一方法,借用已有的 C 的编译器比重造一个成本低多了,而且完全兼容 C 语言。随着这几年 Apple 开发的火热,Objective-C 越来越成为 Apple 不爽的地方,先是恨透了在 GCC 上给 Objective-C 加支持,自己重建了个 Clang,后是干脆重新发明了个 Swift 来彻底代替,用 30 年的时间终于还完了这个技术债。

好的,虽然有了个 Preprocessor,但只能做到把 Smalltalk 风格的代码分析并转译成 C,还需要解决两个问题:

  1. 语言上实现一个 OOP 对象模型

  2. 将 Smalltalk 风格的 Message 机制转换成 C 函数调用

对象模型的设计倒很省事,直接照搬 Smalltalk 的就好了:如 Class / Meta Class / Instance Method / Class Method 这些概念,还有一些关键字如 self / super / nil 等全都是 Smalltalk 的。这步转换在 Preprocessing 过程中就可以完成,因为重写后的 Class 就是原原本本的 C 语言的 Struct,只需要按 Smalltalk 中“类-元类”的模型设置好即可,无需额外的支持。

消息机制就不一样了,要实现向一个 target ( class / instance ) 发送消息名 ( selector ) 动态寻找到函数实现地址 ( IMP ) 并调用的过程,还要处理消息向父类传递、消息转发( Smalltalk 中叫 “Message-Not-Understood”)等,这些行为无法在 Preprocessing 或 Build Time 实现,需要提供若干 运行时 的 C 函数进行支持,所有这些函数打个包,便形成了最原始的 Runtime 。

所以最初的 Objective-C = C + Preprocessor + Runtime

这样的的话,大概可以把OC上所有的类理为它们都是实例。而为什么乔布斯会选择OC做开发语言,因为这本身就是在高级语言身上再封装了一层的语言。则会让开发者学习成本更低,更多开发者愿意投身于iOS应用的开发。而现在的Swift 的想法也是如此,让语言更简单,让编程更容易。推出workplace 这玩意来辅助也是如此。


小麦
46 声望3 粉丝