В 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; кто-нибудь знает Брэда Кокса или Тома Лава? Они здесь?) Или что говорят как писать имена методов, чтобы функция не нужна. Основным преимуществом является удобочитаемость и возможность записи (что похоже на читаемость, только ... вы знаете), поскольку это означало бы, что вы могли бы писать имена методов, которые еще больше напоминают предложения естественного языка. Такие, как -(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication
(на что указывает Мэтт Галлахер в "Какао с любовью"-(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;
}