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 —— 啊,世界清净了。