【发布时间】:2011-05-27 16:04:00
【问题描述】:
在 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 之类的东西(Matt Gallagher 指出 on "Cocoa With Love" 在删除形式参数时会有点混乱)可以命名为 -(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;
}
【问题讨论】:
-
无法解释不可能的原因,但为什么会这样呢? Apple 会将方法命名为“takeAndRun:”和“takeAndDontComplain:”;)
-
或
takeAndRunWith:(id)theMoney和takeAndDon'tComplainAbout:(id)yourMedicine。当然,语法上很尴尬。 -
感谢您提出这个问题——这是一个非常有趣的问题。我去问问。
-
偶尔强迫的语法尴尬让我想要这个功能。
-
好问题。顺便说一句,编译器对这样命名的方法没有问题:
- (void) :(id)theMoney;或- (void) :(id)obj1 :(id)obj2;。所以选择器只包含冒号就可以了。 ;-)
标签: objective-c selector language-design