在 Objective-C 中,如果最后一个组件没有参数,就不能声明方法名。例如,以下内容是非法的。
-(void)take:(id)theMoney andRun;
-(void)take:(id)yourMedicine andDontComplain;
为什么 Objective-C 被设计成这样?是不是只是 Smalltalk 的一个神器,没人觉得有必要处理掉?
这种限制在 Smalltalk 中是有意义的,因为 Smalltalk 在消息调用周围没有分隔符,所以最后一个组件将被解释为最后一个参数的一元消息。例如,BillyAndBobby take:'$100' andRun
将被解析为 BillyAndBobby take:('$100' andRun)
。在 Objective-C,这无关紧要,因为那里需要方括号。
支持无参数选择器组件不会在所有通常的语言度量方式中获得太多,因为程序员选择的方法名称(例如 runWith:
而不是 take:andRun
)不会影响程序的函数语义,也不会影响语言的表达能力。实际上,具有无参数组件的程序相当于没有参数组件的程序。因此,我对声明这样一个特性是不必要的答案不感兴趣(除非这是 Objective-C 设计者所陈述的原因; 是否有人碰巧认识 Brad Cox 或 Tom Love?他们在这里吗?)或者说如何编写方法名,这样就不需要这个特性了。主要的好处是可读性和可写性(就像可读性一样,只是... ... 你知道的) ,因为这意味着你可以写出更接近自然语言句子的方法名。像 -(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication
这样的(Matt Gallagher 指出,当您删除形式参数时,“爱的可可”有点令人困惑)可以命名为 -(BOOL)application:(NSApplication*)theApplication shouldTerminateAfterLastWindowClosed
,因此将参数紧挨着适当的名词。
例如,Apple 的 Objective-C 运行时完全能够处理这类选择器,那么为什么编译器不能呢?为什么不在方法名中也支持它们呢?
#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;
}