返回

消息机制的本质,多层遍历构建多层寻根关系

见解分享

如今已是秋风萧瑟,早就不复炎炎夏日,回忆那轰轰烈烈的夏日,印象最深的就是电闪雷鸣的夜晚,闪电像一道道利剑撕破了黑暗的天空,一声声轰鸣将我们从睡梦中惊醒。当时就想研究一下闪电是怎么产生的,后来看电视时,给我的答案就是闪电是云和云之间或者云和地之间产生的,具体细节也不知道,我就抛出第二个问题,闪电是怎么在云和云之间或者是云和地之间穿过的?当我把这个问题抛给家人时,得到的是眼神,一个表示不解眼神。

又是一场雨过天晴后,我还在想,闪电是怎么产生的。这时,我拿起手机开始搜索闪电是怎么产生的,文章内容很容易看懂,就是因为云层相互摩擦产生的静电太多,一边负电一边正电,两边电荷达到一定程度后,电荷会迅速流动到对方,同时会产生高温,瞬间发光发热,这就是我们看到的闪电。后来,我还在网上搜索,闪电是怎么样从云和云之间穿过的?这次出来的结果非常有意思,是说闪电会寻找一个相对容易的路径,利用这些路径快速的从云和云之间穿过的,这个相对容易的路径通常是空气湿度大的区域。为什么是空气湿度大的区域呢?因为空气湿度大的区域,电阻较小,所以闪电会走近路,从空气湿度大的区域快速的从云和云之间或者是云和地之间穿过的。

说到穿,我就想起了我们程序中对象也是可以进行穿的,我们使用消息就可以在不同的对象之间穿来穿去,这个过程就是对象消息发送的过程。消息发送分为两步,第一步,找到接收消息的对象;第二步,将消息发送给对象。我们之前一篇文章,就是分析了怎么通过一个消息找到一个对象。今天,我们再分析一下,如果第一次没有找到对象,会有什么操作?

前面我们也说过了,一个对象必然会有类,类会有一些方法,这些方法都是可以响应消息的,每一个方法就是这个对象的接收者。我们发送一个消息,如果对象实现了这个消息,那么就可以直接找到这个对象的接收者。如果对象没有实现这个消息,怎么办呢?我们当然不能简单的说找不到,然后就结束了。因为,有时候有些方法你没看到,不代表真的没有。例如,有一个NSMutableString类,它的父类是NSString,但是,NSMutableString实现了insertString方法,而NSString并没有实现insertString方法。这个时候,NSMutableString调用insertString方法,怎么找到这个方法的接收者呢?

为了解决这个问题,Objective-C用多层遍历的方法,构建多层寻根关系。第一步,NSMutableString没有insertString方法,于是向父类NSString请求;第二步,NSString同样没有insertString方法,于是向父类NSObject请求;第三步,NSObject没有insertString方法,那么就说明在NSObject的父类当中没有这个insertString方法,那就说明NSObject及其子类都没有实现这个insertString方法。

现在,我们在实现一个方法之前,都会声明一个方法的声明。例如:

- (void)insertString:(NSString *)aString atIndex:(NSUInteger)loc;

声明的作用,就是为了让编译器检查我们是否实现了这个方法,如果编译器发现我们没有实现这个方法,就会向父类发出警告。在NSMutableString中,当编译器发现了NSMutableString没有实现insertString方法时,会向NSString发出警告。这样,就可以保证当程序员使用这个类时,就知道这个类没有实现这个方法,然后就不会再向这个类发送这个方法的消息了。

多层遍历的方法,构建多层寻根关系,就是消息发送的底层原理。当我们向一个对象发送消息时,如果对象没有实现这个消息,就会向父类请求,直到找到这个消息的接收者或者找到父类的父类。如果在父类的父类中都没有找到这个消息的接收者,那就说明这个消息不能被这个对象响应。