为什么Objective-C方法名称的最后一部分需要参数(当有多个部分时)?

在Objective-C中,不能声明最后一个组件不带参数的方法名称。 例如,以下是非法的。

-(void)take:(id)theMoney andRun; -(void)take:(id)yourMedicine andDontComplain; 

Objective-C为什么这样devise? 这仅仅是一个Smalltalk的人造产品,没有人看到需要摆脱?

这个限制在Smalltalk中是有意义的,因为Smalltalk没有围绕消息调用的分隔符,所以最终的组件将被解释为最后一个参数的一元消息。 例如, BillyAndBobby take:'$100' andRun将被parsing为BillyAndBobby take:('$100' andRun) 。 Objective-C中的方括号是必需的。

支持无参数的select器组件不会在所有测量语言的通常方式中获得很多,因为程序员select的方法名称(例如runWith:而不是take:andRun )不会影响程序的function语义,也不会影响程序的function语义语言的performance力。 事实上,一个带有无参数组件的程序是alpha相当于一个没有。 因此,我对那些没有必要声明这样一个特性的答案并不感兴趣(除非Objective-Cdevise者声明的原因,是否有人知道Brad Cox或Tom Love?他们在这里?)或者说如何编写方法名称,以便不需要该function。 主要的好处是可读性和可写性(就像可读性,只有…你知道),因为这意味着你可以写出更接近自然语言句子的方法名称。 -(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication Matt Gallagher 在“Cocoa With Love”中指出有点混乱,当你放弃正式参数时)可以被命名为-(BOOL)application:(NSApplication*)theApplication shouldTerminateAfterLastWindowClosed ,从而将参数紧靠在适当的名词旁边。

苹果的Objective-C运行时(例如)完全能够处理这些types的select器,为什么不编译器? 为什么不在方法名称中支持它们呢?

 #import <Foundation/Foundation.h> #import <objc/runtime.h> @interface Potrzebie : NSObject -(void)take:(id)thing; @end @implementation Potrzebie +(void)initialize { SEL take_andRun = NSSelectorFromString(@"take:andRun"); IMP take_ = class_getMethodImplementation(self, @selector(take:)); if (take_) { if (NO == class_addMethod(self, take_andRun, take_, "@@:@")) { NSLog(@"Couldn't add selector '%@' to class %s.", NSStringFromSelector(take_andRun), class_getName(self)); } } else { NSLog(@"Couldn't find method 'take:'."); } } -(void)take:(id)thing { NSLog(@"-take: (actually %@) %@",NSStringFromSelector(_cmd), thing); } @end int main() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; Potrzebie *axolotl=[[Potrzebie alloc] init]; [axolotl take:@"paradichloroaminobenzaldehyde"]; [axolotl performSelector:NSSelectorFromString(@"take:andRun") withObject:@"$100"]; [axolotl release]; [pool release]; return 0; } 

这是Brad Cox。 我原来的回答误解了这个问题。 我认为非常快是一个硬编码的扩展,可以触发更快的消息传递,而不是一种语法糖。 真正的答案是Smalltalk不支持它,也许是因为它的parsing器不能处理(假定的)模糊性。 虽然OC的方括号可以消除任何含糊不清的地方,但我根本没有想到从Smalltalk的关键字结构出发。

21年的编程Objective-C,这个问题从来没有跨过我的脑海。 鉴于语言devise,编译器是正确的,运行时function是错误的()。

交错参数与方法名称的概念总是意味着,如果至less有一个参数,则最后一个参数总是方法调用语法的最后部分。

没有想太多,我敢打赌,有一些句法bugaboos不执行当前模式。 至less,这会让编译器更难编写,任何有可选元素交织expression式的语法总是难以parsing。 甚至可能有一个边缘的情况下,平坦防止它。 当然,Obj-C ++会让它变得更具挑战性,但是直到基础语法已经成熟之后的几年,它才与语言相结合。

至于为什么Objective-C是这样devise的,我怀疑答案是这个语言的原始devise者并没有考虑允许交错语法超越最后一个参数。

这是一个最好的猜测。 我会问他们的一个,当我发现更多的时候更新我的答案。


我问布拉德考克斯这件事,他非常慷慨地回答详细(谢谢,布拉德!!):

当时我的工作重点是尽可能多地复制C语言中的Smalltalk,并尽可能高效地执行此操作。 任何备用的周期都会让普通的消息传递更快。 有没有想过一个专门的消息选项(“真的很快?”[ bbum:我用'doSomething:withSomething:reallyFast'作为例子 ]),因为普通的消息已经尽可能快了。 这涉及手动调整C语言消息器的汇编程序输出,这是一种可移植的恶梦,以至于一些(如果不是全部的话)稍后被取出。 我记得那个手机黑客的速度非常快, 关于两个函数调用的代价; 一个进入消息逻辑,其余的进行方法查找。
静态的input增强function后来被史蒂夫·纳罗夫(Steve Naroff)和其他人在Smalltalk的纯dynamicinput之上加上了。 我只有有限的参与。

去读布拉德的答案!

只是为了您的信息,运行时并不关心select器,任何Cstring都是有效的,您也可以像这样做一个select器:“== + === + — ___ – ” ¨^ ::::::“没有参数运行时会接受它,编译器不能或否则不可能parsing。 在select器方面绝对没有理智的检查。

我假设它们在Objective-C中不被支持,因为它们在Smalltalk中也是不可用的。 但是,这与你想象的有不同的理由:它们不是必需的。 需要的是支持0,1,2,3,…参数的方法。 对于每一个参数,已经有一个工作语法来调用它们。 添加任何其他语法只会造成不必要的混淆。

如果你想要多字无参数select器,为什么停止一个额外的单词? 有人可能会问这个问题

  [axolotl perform selector: Y with object: Y] 

也变得支持(即select器是一个单词序列,一些冒号和一个参数,其他人不)。 虽然这是可能的,但我认为没有人认为这是值得的。