第五章:方括号的艺术 —— 不是调用,是发消息

5.1 从 object.method()[object method]

如果你来自 Java、C#、或者 Swift,你习惯了“点语法”。 dog.bark() —— 意思是:命令狗叫。这也是大多数现代语言的逻辑:函数调用(Function Call)。 你拿到一个对象的地址,直接跳转到它内存里的那个函数代码块去执行。

但在 Objective-C 里,事情变得哲学了起来。 [dog bark] —— 意思是:向狗发送一个“bark”的消息

区别在哪?

  • 函数调用:是很生硬的。编译器必须知道 dog 有没有 bark 方法。如果没有,编译报错。
  • 发消息:是很礼貌的。我只是把“bark”这张纸条递给 dog。至于 dog 看了纸条是高兴地叫两声,还是把纸条撕了(忽略),或者是转交给旁边的猫(消息转发),那完全取决于 dog 心情(Runtime 决议)。

这就是 OC 动态性的根源。因为是“发消息”,所以你可以给 nil 发消息(对着空气说话,不会有人打你),所以你可以在运行时把消息截获下来换成别的。

5.2 多参数的魅力:像写句子一样写代码

C++ / Java 的函数多参数调用长这样: subString(0, 5) 有时候你看着这两个数字,不仅陷入沉思:哪个是 Start?哪个是 Length?还是 End?

Objective-C 就在这里展示了它的文科生气质[string substringFromIndex:0 toIndex:5] (注:虽然 OC 实际 API 是 substringWithRange: 等,但这里举例展示标签(Label)的意义) 或者更真实的: [array insertObject:obj atIndex:5]

每一个参数前面都有一个介词或者标签。这让 OC 的代码读起来就像一句英语长难句。 [waiter bringCoffee:hot toTable:5 withSugar:YES]

这被 Swift 完美继承了下来。

5.3 嵌套的方括号:无数个框

当你想把这一连串操作连起来时,噩梦开始了:

[[[[string uppercaseString] substringFromIndex:1] stringByAppendingString:@"World"] length]

这就是著名的“方括号盖饭”。 为了读懂这行代码,你得像剥洋葱一样,从最里面那个括号开始往外剥。 这也是为什么后来 OC 引入了点语法(Dot Syntax)来访问属性(Properties),试图挽救一下大家的视力。 string.uppercaseString.length —— 啊,世界清净了。

使用 Hugo 构建
主题 StackJimmy 设计