1
66450146 2013-10-08 16:24:43 +08:00
只有第一种
整行都是方法名,而不是像你想的一样第一个是参数名。可以认为第一个参数的名称隐含在方法名的第一部分里面 |
2
spoony 2013-10-08 16:25:13 +08:00
感觉和人类语言习惯很接近
|
3
bytelee 2013-10-08 16:46:42 +08:00
一开始怪 后来你会喜欢上他的
|
4
PrideChung 2013-10-08 16:49:46 +08:00
习惯了就好,这种风格的好处是你不太可能搞错参数顺序。
|
5
chchwy 2013-10-08 16:54:11 +08:00
函數的簽名是
UIColor colorWithRed:green:blue:alpha: 別誤解為python那種named parameter了,red green blue alpha不能互換順序,也不能省略的,整串都是函數的名字。 |
6
sharkli 2013-10-08 16:59:31 +08:00
习惯了很舒服的。参数不会写错哈哈。
|
8
Ricepig OP @chchwy 让我觉得蛋疼的是
为什么不是UIColor.color(red, green, blue, alpha)。 我并不是觉得blue:xxx,green:xxx这种方式蛋疼,而是觉得"第一个参数特殊的语法,并影响到函数名"这种规则很奇怪。 |
10
alexrezit 2013-10-08 17:10:19 +08:00 1
@Ricepig
你觉得 blah.blahblah(-1, NULL, 0, 0, 1, TRUE, NULL, 0, -1) 这样就爽了? 你知道哪个参数是做什么的? 而且第一个参数哪里有特殊语法了? 我写了三年多 Objective-C 怎么不知道? |
11
PrideChung 2013-10-08 17:14:14 +08:00
@Ricepig 因为 Objective-C 不是Java。第一个参数名隐含这个问题不大,一般方法的命名都会写成 initWithFoo, barForFoo 这种风格,读起来就像英语一样。
PS: Objective-C 方法命名还相当注意语法的正确性,例如时态和单复数。例如 NSArray 检查一个元素是否存在的方法是 containsObject: |
12
Ricepig OP @alexrezit 麻烦仔细看一下贴
第一个参数隐含了名字,造成第一个参数非常特殊,首先它是唯一不用指定参数名的参数,其次方法在命名时还要考虑隐含第一个参数的名字,就出现了colorWithRed这种蛋疼的方法名。 |
13
Ricepig OP @PrideChung 语法的正确性在很多库里都是被特别关注的。但是Objective-C的命名里最蛋疼的是很多类都有前缀,例如NS。就不能使用namespace吗?
为什么Java里问题就大,ObjC问题就不大?java照样可以写Color.CreateWithRed(255)。就我说的这个例子,感觉并不像英语,后面接一大溜那是啥? 其实我吐槽的还是第一个参数的特殊性。 |
14
alexrezit 2013-10-08 17:18:58 +08:00
|
16
txx 2013-10-08 17:30:24 +08:00
|
17
fgwww 2013-10-08 17:30:32 +08:00
color with Red green blue alpha...这么读起来有什么不对?
难道要color ,red green blue alpha? |
18
elden 2013-10-08 17:31:52 +08:00
objc中没有命名参数,冒号前面的描述只是它的方法签名的组成之一。
|
19
PrideChung 2013-10-08 17:33:31 +08:00
|
20
refresh 2013-10-08 17:38:59 +08:00
初用是很不习惯,用久了也蛮好的,只是有点冗长,但好处是可以不用看文档就能读代码,不好的地方是英文不好的人写出的代码可能会让你误解
|
21
chchwy 2013-10-08 17:44:35 +08:00
|
22
Ricepig OP @PrideChung 请问写成Color.Create(red:255,blue:255,green:255,alpha:1.0)是不是感觉更加清楚一点呢?
|
23
Ricepig OP @txx
@fgwww @elden @chchwy 请教一个问题,ColorWithRed这个部分,是表示一个动作(消息),还是表示一个动作(消息)加一个参数?为什么要把消息设计得这么纠结?每个部分我认为担负一种责任就够了,但是这里负责了两种,首先它表达了要干什么(动作),其次它表示了第一个参数是什么。 这种语法在只有唯一参数的方法或函数调用时是比较简洁的,一旦参数超过一个,就显得有些诡异。 正如我举的例子,为啥就有colorWithRed,没有colorWithBlue,colorWithGreen? 当然,可以说,这是一个习惯问题。这么说的话,如果当年ObjC设计成[UIColor colorWithBlueNRed:255,255 green:255 alpha:1.0]也完全没有问题。 |
24
chchwy 2013-10-08 17:57:48 +08:00
我懂你的意思了。
其實還是一句老話,整句都是函數名字。 不要理解為前半段是函數名字,後半段是參數名字,不是這樣的。 colorWithRed:green:blue:alpha: <= 這整個都是函數名字。 只是這個函數名字中間有挖些洞,可以填入參數值。 |
25
Ricepig OP @chchwy 你说的“整句都是函数名字”,在一般书籍中指的是函数“签名”(Signature),它包含函数名、参数列表、返回类型等。
或者,用你的概念来说,为什么函数名字不是createColor:red:green:blue:alpha? |
26
ritksm 2013-10-08 18:04:58 +08:00
没看懂LZ想表达什么
大家都说了colorWithRed:green:blue:alpha:这一个才是函数名 不是你所谓的签名 函数名懂么? def foo(bar): pass 等同foo |
27
chchwy 2013-10-08 18:05:03 +08:00
我可以舉個例子說明
比方說複製檔案的函數是 NSFileManager copyItemAtPath:toPath:error: 具體用法是 [myFileManager copyItemAtPath:@"FileA" toPath:@"FileB" error:nil]; 你能說消息名是copyItemAtPath: 第一個參數名字叫Path 第二個叫toPath嗎? 當然不是的。 copyItemAtPath:toPath:error: <=這整個都是消息的名字,只是消息名稱中間可以填洞。 整句代碼就像是英文句子一樣,後半段你可以為了清晰而寫明參數名,但是不寫也是可以的。 像是有的數值運算庫 就用 [Fraction set:1 over:2] 來表達1/2的概念。 |
28
Ricepig OP @chchwy 我不认为copyItemAtPath:toPath:error比copy(from:xxx, to:xxx, err:xxx)要清晰。
|
29
Ricepig OP |
30
chchwy 2013-10-08 18:17:55 +08:00
牽扯到清晰就跑題了,大哥。
我只是說明這樣的函數名並沒有任何的邏輯衝突之處。清晰與否則是個人主觀。 你喜歡用括號就用括號表達參數名,你當然可以認為這樣比較好,只可惜Objc並沒有參數名,也沒有用括號。 Objc的前身Smalltalk也不是用括號。 |
31
Ricepig OP @chchwy 另外,从[Fraction set:1 over:2]来看,我不认为分子比分母有更大的重要性,为何分母就需要用over标识,而分子直接跟着set就可以?
另外,如果方法的编写者在命名的时候出于某种原因,没有包含"AtPath","withRed",方法调用者是不是要去猜第一个参数该是啥? |
32
Ricepig OP @chchwy 不是说括号,简单来说,我是对“colorWithRed”中color和red不分开表示无法理解,既然green和blue都是分开的。至于用空格,还是用括号分开,见仁见智。
|
33
ritksm 2013-10-08 18:21:01 +08:00
|
34
PrideChung 2013-10-08 18:23:10 +08:00
@Ricepig 我不认为 copy(from:xxx, to:xxx, err:xxx) 比 copyItemAtPath:toPath:error 要清晰。
|
35
goodan 2013-10-08 18:24:35 +08:00
卤煮偏离轨道了。围观中~~
|
36
chchwy 2013-10-08 18:27:48 +08:00
原來如此,那這個就是語法設計議題了。
要不要把名字和參數名切開只能說是當初語言設計者的喜好問題了。 我可以說說objc的背景 這種參數可以穿插在名字中間的寫法是從Smalltalk來的,Objc精神上是繼承自Smalltalk,Smalltalk 並非 C-like的語言。 只是迫於現實的緣故,Objc設計之初需要相容於C語言。所以用C的語法來思考,可能不夠妥當。 看看Wiki的Smalltalk條目,看看他的語法,或許你比較可以理解 https://en.wikipedia.org/wiki/Smalltalk |
37
Ricepig OP @ritksm 括号不括号没问题的,是不是用空格分隔token也没问题
只是觉得语言应当简洁、一致。而ObjC中这种“函数名”对第一个参数和后面其他参数有点儿区别感到怪异。 @PrideChung 你的这个调用,我可以问一下,为什么不写成copyItemToPath:atPath:error呢? |
38
alexrezit 2013-10-08 18:28:15 +08:00 1
@Ricepig
首先那个不叫 "函数" (function), 叫做 "method". 而且那个就是 method 名, 它跟其他语言是不一样的, 它相当于 ColorWithRedGreenBlueAlpha(red, green, blue, alpha), 而不是 Color(Red:red, Green:green, Blue:blue, Alpha: alpha). 你根本就是自以为是地把它和一个毫不相干的东西联系起来. |
40
Ricepig OP @PrideChung 或者函数设计者写成了copyItem:atPath:error,还能理解吗?
|
41
chchwy 2013-10-08 18:32:32 +08:00
> 或者函数设计者写成了copyItem:atPath:error ,还能理解吗?
大哥,你這句就是純找碴了,這不就是命名習慣不佳嗎? 干語言設計何事? |
42
icyalala 2013-10-08 18:36:34 +08:00 2
首先说一下底层的实现:
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 |
43
Ricepig OP @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,我是否自以为是与讨论问题无关,请遵循“对事不对人”方式,谢谢。 |
44
icyalala 2013-10-08 18:37:47 +08:00
擦。。竟然有名字叫selector的人。。。上面竟然还@到了。。
|
45
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 相对于其他语言独有的优势. |
47
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的命名规则可读性增强了不少 |
48
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? |
49
Ricepig OP @icyalala 我明白你说的“方法名”,事实上就是“函数签名”,只是换了一个叫法。
在其他语言中,如果只申明color(red,blue,green,alpha),则只存在这一个函数,不存在别的color函数。 不是存在敌意,只是觉得怪异。“有点儿奇怪”我不觉得是完全负面甚至是敌意的说法吧。 |
51
Ricepig OP @hengxin196 这个没有说服力,尤其是对vb和python这种在函数调用时显式指定参数的语言。
|
52
Ricepig OP @alexrezit 这种我并不觉得怪异,green,blue,red是并列的存在,顺序也是由习惯决定,这都没什么可吐槽的。可以吐槽的就是withRed和color放在一起了,没分割。
|
55
blahnice 2013-10-08 18:55:02 +08:00
都是批楼主的,其实我觉得楼主的逻辑很对,很值得拿来探讨下。
倒是很多答题的人没理解楼主在说什么,楼主说语法他们说习惯,楼主说习惯他们说设计,楼主说设计他们说自然文法理解,楼主说自然文法理解恰好就是我的问题所在,他们就直接说楼主有偏见了。 以上不包括 @icyalala @chchwy 两位认真理解楼主意思并解释讨论的朋友。 另外再感谢下这两位同学的答案,其实楼主提这个问题,一个原因是的确需要从底层llvm实现解释才能说清楚区别,另一个问题是现在国内很多objc教材都是「第一个参数隐含了名字,造成第一个参数非常特殊」这种奇特角度来描述objc这个method call的语法的,而不是从底层实现去解释。这很多是中文书本身作者理解水平或者翻译的问题。 直接导致了很多人学习的别扭和疑问,实际上我学习的时候也碰到过这个问题纠结许久。为毛非要把动词和第一个参数两者复合作为method名,而不是分开更清晰。 |
56
fgwww 2013-10-08 19:00:01 +08:00
RGB是早就约定俗成的,在上上个世纪。。。
|
57
Ricepig OP @blahnice 谢谢你的理解
我现在能够从诸多回复中得到的信息,就是 1. 这是为了偏向底层实现 2. 这是一种类似语法糖的东西,为了提高代码可读性。 3. 这是从smalltalk延续而来的语法 好吧,ObjC的语法至今还不习惯,不习惯的程度更甚于Lisp |
58
otakustay 2013-10-08 19:36:45 +08:00
我觉得根本性的问题在于,楼主一定要理解colorWithRed:green:blue为“方法签名”,但其实在objc中,这东西就是方法名,名!不是签名!方法签名是“这个方法名+返回值+每个参数的类型”合在一起才成立的,你绝对不能把colorWithRed:green:blue这一串东西当成签名,因为它不能代表且仅代表一个函数/方法/消息
所以如果楼主一定要坚持说colorWithRed:green:blue这个是方法签名而不是名的话,就完全是用其它语言的所谓常识的一部分(不是全部)去理解一个独特的语言,一切讨论都无法成立。 就好比中国人去问一个日本人:中文和英文都说“我吃饭”,日语为啥说“我饭吃”。这纯粹是文化的差异你非要坚持自己才是对的就是找打嘛 |
59
dorentus 2013-10-08 19:39:25 +08:00
提出「第一个参数隐含了名字,造成第一个参数非常特殊」这种说法的教材也真够奇怪的……
我接触 Obj-C 的时候,没看啥教材;刚开始有些迷惑,不过后来意识到那整个是个方法签名后,就自然地接受了。 至于说要和 python 的那种比较起来,可读性貌似差不多吧。Objective-C 出来的时候 python 还没有,又是参照的 Smalltalk 做的面向对象系统,要真做成了和后来 python 类似的样子,那得是多大的巧合啊。 |
60
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 |
61
66450146 2013-10-08 19:53:42 +08:00
@Ricepig 其实只是习惯的不同
比如 new UIColor(134/255.0f, 198/255.0f, 124/255.0f, 1.0) 这样的语法应该更容易习惯(照顾 C++ 选手),也更贴近操作系统,但是可读性恐怕就差一点了 至于如果有人命名糟糕,这个无论是什么语言都难以避免,只能说,Obj-C 用这种方式,尽量的让程序员有可能能写出可以直接用英语读出就可以理解的代码 从一种代码风格转向另一种不总是容易的,尤其是像 Obj-C 这种设计一开始就比较奇葩的语言,多写点代码,多读点英语,自然就习惯了 |
62
otakustay 2013-10-08 19:55:42 +08:00
@dorentus 正如你摘录的,签名包含“方法关键字(objc里是中括号?),返回值,一个或多个签名关键字,参数类型,参数名称。很明显,colorWithRed:green:blue不包含上面说到的全部,因此叫签名我认为是不合理的
|
63
otakustay 2013-10-08 19:56:37 +08:00 1
@66450146 让我想起strcpy(a, b)函数……每次都要查下文档才知道哪个是from,哪个是to,真心痛苦……
|
65
xuzhe 2013-10-08 21:48:32 +08:00
按楼主你从别的语言里学来的“函数签名”理论,你觉得以下两个方法放一起能编译过么?
- (BOOL)test1:(NSString *)test1 test2:(NSString *)test2 { } - (void)test1:(NSInteger)test1 test2:(NSInteger)test2 { } |
67
biaobiaoqi 2013-10-08 22:15:23 +08:00
说实在的,lz的思路之前也有过。不过后来习惯了-,-
没什么语言能满足所有人的偏好,或者完美的合理吧。 一定要讨论个objc当初的设计为何是这样子,个人不觉得有意义。倒是觉得这个看法本身是不错的,我也这么想过,这就是我的第一反应『它看起来比较奇怪,第一个参数和方法名混在一起了』。或许将来某种新语言中会有更好的实现呢-,- |
68
amoblin 2013-10-08 22:43:40 +08:00
楼主的逻辑其实很正确,理论上,应该是这样的函数:
[UIColor colorWith red:0.5f green:0.5f blue:0.5f alpha:1.0f]; 其中colorWith表达整个函数名的作用(是生成color用滴),统领后面的参数:red,green,blue,alpha 然而实际使用时,colorWith和red有一个空格,浪费空间和时间(maybe),于是合在一起写了,类似于文字的连写 理想化的东西和现实总是有差距的,类似这样的问题其实有很多的。 楼主是一个完美主义者/理想主义者。 |
69
nil 2013-10-08 23:19:58 +08:00
刚开始看不懂楼主想说什么,后来看了@amoblin 的回复,才觉得刚开始学习语法的时候也有和楼主类似的困惑,不过后来这都不是重点了。。。
有人说lisp最优雅的部分是S表达式, 我觉得smalltalk最优雅的地方应该就是named parameters了,这么点语法糖给可读性带来质的飞跃,主流的编程语言中该特性支持最好的应该就是objc了,再加上xcode的智能补全,这货分明就应该统治世界,而不是java,javascript之流。 |
72
chchwy 2013-10-08 23:31:59 +08:00
可惜上次GNUStep的募資沒有成功,錯失了一次把Objective-C推出Win/Linux的機會。
|
73
Ricepig OP @chchwy Objective-C个人感觉在语言层面上并没有太多亮点,可能特性比C多一点,所谓可读性好一点吧。个人的感官来说,即使结合了Xcode,ObjC仍旧显得比较繁琐,生产效率不太高。它在保留大部分性能的情况下,比C/C++是强了不少,但是这一步仍旧稍显不够大,尤其在这个时代。
|
74
anson0370 2013-10-08 23:48:37 +08:00
难道不是这样么?
+ (CIColor *)colorWithRed:(CGFloat)r green:(CGFloat)g blue:(CGFloat)b; 这玩意儿是方法签名(包含返回类型、方法名、参数列表) colorWithRed:green:blue: 这玩意儿是方法名 r, g, b 这三个才是参数名而不是 green 和 blue,并且参数类型都是 CGFloat 调用时参数的插入位置被放到了方法名中间,和绝大部分语言的直觉不符,但这也说得通嘛 |
75
mingming 2013-10-08 23:50:18 +08:00
我觉得如果是这样的话就顺眼多了。
[UIColor colorWithRed:134/255.0f colorWithGreen:198/255.0f colorWithBlue:124/255.0f alpha:1.0] |
77
clippit 2013-10-09 00:05:06 +08:00
楼主的两枚吐槽帖纷纷雄踞热门排行榜,功力深厚啊!
|
78
so898 2013-10-09 02:57:52 +08:00
与其吐槽赚分不如多写点代码
想当年因为我对于UIColor的CGFloat的憎恨,直接导致了一套专门写给这货,使得我不用每次除以255的代码的出现……之后的生活,风调雨顺…… |
80
chchwy 2013-10-09 09:59:37 +08:00
@Ricepig
如果你想想Objc的出生時間是1983年,比Java、Ruby、Python等等語言都大了五歲到十歲, 你就不會意外它的語法設計如此了。Objc的老語法也是到了近兩年(2011年左右),Apple開始投入Clang項目之後,才慢慢有一些改良與演進。 Objc的亮點是在Objc Runtime,比方說可以透過 [myObject responseToselector:@selector(myMethod:)]; 來判別對象是否能回應消息,這可是動態語言才有的特性阿,C/C++是連想都不敢想的。 Objc有動態語言的特性,強型別,同時完全兼容C語言,其實想想也明白它是一個妥協之下的產物。 |
82
chisj 2013-10-10 09:34:35 +08:00
楼主写过两年就会爱不释手的。
|