关注码农话题
做一个实实在在的内行人

Objective-C 消息传递

Objective-C最大的特色是承自Smalltalk的消息传递模型(message passing),此机制与今日C++式之主流风格差异甚大。Objective-C里,与其说对象互相调用方法,不如说对象之间互相传递消息更为精确。此二种风格的主要差异在于调用方法/消息传递这个动作。C++里类别与方法的关系严格清楚,一个方法必定属于一个类别,而且在编译时(compile time)就已经紧密绑定,不可能调用一个不存在类别里的方法。但在Objective-C,类别与消息的关系比较松散,调用方法视为对对象发送消息,所有方法都被视为对消息的回应。所有消息处理直到运行时(runtime)才会动态决定,并交由类别自行决定如何处理收到的消息。也就是说,一个类别不保证一定会回应收到的消息,如果类别收到了一个无法处理的消息,程序只会抛出异常,不会出错或崩溃。

C++里,送一个消息给对象(或者说调用一个方法)的语法如下:

obj.method(argument);

Objective-C则写成:

[obj method: argument];

此二者并不仅仅是语法上的差异,还有基本行为上的不同。

这里以一个汽车类(car class)的简单例子来解释Objective-C的消息传递特性:

[car fly];

典型的C++意义解读是”调用car类别的fly方法”。若car类别里头没有定义fly方法,那编译肯定不会通过。但是Objective-C里,我们应当解读为”发提交一个fly的消息给car对象”,fly是消息,而car是消息的接收者。car收到消息后会决定如何回应这个消息,若car类别内定义有fly方法就运行方法内之代码,若car内不存在fly方法,则程序依旧可以通过编译,运行期则抛出异常。

此二种风格各有优劣。C++强制要求所有的方法都必须有对应的动作,且编译期绑定使得函数调用非常快速。缺点是仅能借由virtual关键字提供有限的动态绑定能力。Objective-C天生即具备鸭子类型之动态绑定能力,因为运行期才处理消息,允许发送未知消息给对象。可以送消息给整个对象集合而不需要一一检查每个对象的类型,也具备消息转送机制。同时空对象nil接受消息后默认为不做事,所以送消息给nil也不用担心程序崩溃。


入职你的梦想 VS 变现你的技术

IT面试宝典码农市场