在 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
) 不影响程序的功能语义,也不影响语言的表达能力。事实上,带有无参数组件的程序与没有无参数组件的程序在 alpha 版本上是等价的。因此,我对那些声称不需要这样的功能的答案不感兴趣(除非这是 Objective-C 设计师所陈述的原因;有人碰巧认识 Brad Cox 或 Tom Love?他们在这里吗?)或者说如何编写方法名称以便不需要该功能。主要好处是可读性和可写性(这就像可读性,只是……你知道),因为这意味着你可以编写更类似于自然语言句子的方法名称。喜欢的-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication http://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSApplicationDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/NSApplicationDelegate/applicationShouldTerminateAfterLastWindowClosed:(马特·加拉格尔指出关于“可可与爱” http://cocoawithlove.com/2009/06/method-names-in-objective-c.html当你删除形式参数时有点混乱)可以命名-(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;
}