稍微吐槽一下ObjC的函数调用

2013-10-08 16:20:38 +08:00
 Ricepig
ObjC的方法调用(消息传递)的写法首先是类/对象,然后是消息,然后是参数。这别扭的地方在于函数名和后面的参数名并列。举个栗子:

[UIColor colorWithRed:134/255.0f green:198/255.0f blue:124/255.0f alpha:1.0]

这尼玛是不是还有

[UIColor colorWithBlue:134/255.0f green:98/255.0f blue:124/255.0f alpha:1.0]



[UIColor colorWithGreen:134/255.0f red:198/255.0f blue:124/255.0f alpha:1.0]

方法的第一个参数参数名默认,第二个开始指定参数名,怎么写怎么觉得有点奇怪。
6832 次点击
所在节点    程序员
82 条回复
chchwy
2013-10-08 18:32:32 +08:00
> 或者函数设计者写成了copyItem:atPath:error ,还能理解吗?

大哥,你這句就是純找碴了,這不就是命名習慣不佳嗎? 干語言設計何事?
icyalala
2013-10-08 18:36:34 +08:00
首先说一下底层的实现:

ObjC只是在C上面稍微包装了一层运行时。编译的时候,llvm会把objc的消息转换成转换成C的函数调用....所以,这里没有C++的namespace、运算符重载之类的特性。


[UIColor colorWithRed:1.0 green:0.5 blue:1.0 alpha:1.0];

这个方法的调用实际会被llvm翻译成类似下面这样的运行时C方法调用:

id receiver = NSClassFromString(@"UIColor ");
SEL name = @selector(colorWithRed:green:blue:alpha:);
objc_msgSend(receiver, name, 1.0, 0.5, 1.0, 1.0);

看这个msgSend,就是说,苹果实际是想强调"消息发送"这种动态的特性的,这个C++、Java之类语言的编译时绑定有很大的差别。只是大家交流起来,还是用"invoke this method"说的方便。



之后说一下这个语法:
这个方法名是 "colorWithRed:green:blue:alpha:",这是一个完整的"方法名",不可以分割,包含冒号。
这个方法和 "colorWithRed" 是完全不同的两个方法。(如果你直接调用"colorWithRed"这个方法的话,是没有的。。LZ在15楼的理解不对)。

这种语法的好处就是,代码能真正做到自解释,更加贴近自然语言;坏处就是冗长、和其他变成语言的语法格格不入。。


LZ好像是带着敌意去学习新语言,这不是给自己找气生嘛~~ 一旦接受了这种设定,也就不会那么难受了~~

推荐LZ看看这个:http://www.zhihu.com/question/20226719
Ricepig
2013-10-08 18:36:44 +08:00
@alexrezit 我说了,叫method还是叫function都无所谓,你我都明白是指的同一个概念。

但是你没有明白,ColorWithRedGreenBlueAlpha这个名字除了长了一点,其实没问题,因为Red这几个对于函数来说是同等重要的。在C族语言中,你只能写出Color.Create(red, blue, green, alpha),但是在ObjC中,完全可以编写[XXColor color:xxx blue:xxx green:xxx, alpha:xxx],这第一个参数是毛?

我其实明白你们说的,为什么有withRed,其实和color(red:xxx... 是等价的。再强调一遍,我不认为用空格分割还是用括号还是其他符号分割token有任何问题,只是觉得将color和withRed不加分割地写在一起怪异。

PS,我是否自以为是与讨论问题无关,请遵循“对事不对人”方式,谢谢。
icyalala
2013-10-08 18:37:47 +08:00
擦。。竟然有名字叫selector的人。。。上面竟然还@到了。。
alexrezit
2013-10-08 18:38:40 +08:00
@Ricepig
Objective-C 是支持变参的, 例如这两个 method:
+ (CIColor *)colorWithRed:(CGFloat)r green:(CGFloat)g blue:(CGFloat)b;
+ (CIColor *)colorWithRed:(CGFloat)r green:(CGFloat)g blue:(CGFloat)b alpha:(CGFloat)a;
完全可以在设计时写成这样:
+ (CIColor *)color:(CGFloat)r, ...;
参数则为 r, g, b, a, 相当于你习惯的 color(r, g, b, a),
但是为了在使用时让人一眼看出来哪个参数是做什么的就没有写成后者. 这是 OC 相对于其他语言独有的优势.
alexrezit
2013-10-08 18:40:14 +08:00
@Ricepig

如果分开的话就是这样?

+ color red: green: blue:

你不觉得更怪异么?
hengxin196
2013-10-08 18:41:33 +08:00
卤煮这个是方法名:
`colorWithRed:green:blue:`
rgb 给出相应的色值多爽 一目了然, bgb grb 不觉得很别扭把

`为什么不是UIColor.color(red, green, blue, alpha)。`
因为当你填上相应的色值后 UIColor.color(0.5, 0.5, 0.5, 0.5)
这四个0.5 分别代表什么?不看文档很难记住吧 相比之下oc的命名规则可读性增强了不少
fgwww
2013-10-08 18:42:14 +08:00
为什么是color with red green blue alpha而不是with blue green red,也不是with green blue red呢?
那么为什么是RGB而不是GBR或者BGR?
Ricepig
2013-10-08 18:45:14 +08:00
@icyalala 我明白你说的“方法名”,事实上就是“函数签名”,只是换了一个叫法。

在其他语言中,如果只申明color(red,blue,green,alpha),则只存在这一个函数,不存在别的color函数。

不是存在敌意,只是觉得怪异。“有点儿奇怪”我不觉得是完全负面甚至是敌意的说法吧。
Ricepig
2013-10-08 18:46:16 +08:00
@icyalala 可以起名交insert,哈哈
Ricepig
2013-10-08 18:47:57 +08:00
@hengxin196 这个没有说服力,尤其是对vb和python这种在函数调用时显式指定参数的语言。
Ricepig
2013-10-08 18:48:57 +08:00
@alexrezit 这种我并不觉得怪异,green,blue,red是并列的存在,顺序也是由习惯决定,这都没什么可吐槽的。可以吐槽的就是withRed和color放在一起了,没分割。
Ricepig
2013-10-08 18:50:15 +08:00
@fgwww 在RGB没有约定俗成时,你叫BGR也是可以的。

函数名浩如烟海,并不是每个函数名都能“约定俗成”
alexrezit
2013-10-08 18:53:14 +08:00
@Ricepig
没有 with 就不符合自然语言的规律了.
blahnice
2013-10-08 18:55:02 +08:00
都是批楼主的,其实我觉得楼主的逻辑很对,很值得拿来探讨下。
倒是很多答题的人没理解楼主在说什么,楼主说语法他们说习惯,楼主说习惯他们说设计,楼主说设计他们说自然文法理解,楼主说自然文法理解恰好就是我的问题所在,他们就直接说楼主有偏见了。

以上不包括
@icyalala
@chchwy
两位认真理解楼主意思并解释讨论的朋友。

另外再感谢下这两位同学的答案,其实楼主提这个问题,一个原因是的确需要从底层llvm实现解释才能说清楚区别,另一个问题是现在国内很多objc教材都是「第一个参数隐含了名字,造成第一个参数非常特殊」这种奇特角度来描述objc这个method call的语法的,而不是从底层实现去解释。这很多是中文书本身作者理解水平或者翻译的问题。
直接导致了很多人学习的别扭和疑问,实际上我学习的时候也碰到过这个问题纠结许久。为毛非要把动词和第一个参数两者复合作为method名,而不是分开更清晰。
fgwww
2013-10-08 19:00:01 +08:00
RGB是早就约定俗成的,在上上个世纪。。。
Ricepig
2013-10-08 19:13:12 +08:00
@blahnice 谢谢你的理解

我现在能够从诸多回复中得到的信息,就是
1. 这是为了偏向底层实现
2. 这是一种类似语法糖的东西,为了提高代码可读性。
3. 这是从smalltalk延续而来的语法

好吧,ObjC的语法至今还不习惯,不习惯的程度更甚于Lisp
otakustay
2013-10-08 19:36:45 +08:00
我觉得根本性的问题在于,楼主一定要理解colorWithRed:green:blue为“方法签名”,但其实在objc中,这东西就是方法名,名!不是签名!方法签名是“这个方法名+返回值+每个参数的类型”合在一起才成立的,你绝对不能把colorWithRed:green:blue这一串东西当成签名,因为它不能代表且仅代表一个函数/方法/消息
所以如果楼主一定要坚持说colorWithRed:green:blue这个是方法签名而不是名的话,就完全是用其它语言的所谓常识的一部分(不是全部)去理解一个独特的语言,一切讨论都无法成立。
就好比中国人去问一个日本人:中文和英文都说“我吃饭”,日语为啥说“我饭吃”。这纯粹是文化的差异你非要坚持自己才是对的就是找打嘛
dorentus
2013-10-08 19:39:25 +08:00
提出「第一个参数隐含了名字,造成第一个参数非常特殊」这种说法的教材也真够奇怪的……

我接触 Obj-C 的时候,没看啥教材;刚开始有些迷惑,不过后来意识到那整个是个方法签名后,就自然地接受了。

至于说要和 python 的那种比较起来,可读性貌似差不多吧。Objective-C 出来的时候 python 还没有,又是参照的 Smalltalk 做的面向对象系统,要真做成了和后来 python 类似的样子,那得是多大的巧合啊。
dorentus
2013-10-08 19:42:57 +08:00
@otakustay

叫签名似乎也不能算错吧。

「The declaration of a method consists of the method type identifier, a return type, one or more signature keywords, and the parameter type and name information. 」

-- https://developer.apple.com/library/mac/referencelibrary/GettingStarted/Learning_Objective-C_A_Primer/#//apple_ref/doc/uid/TP40007594-CH1-SW11

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/84873

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX