In Objective-C, non è possibile dichiarare nomi di metodi in cui l'ultimo componente non accetta un argomento. Ad esempio, quanto segue è illegale.
-(void)take:(id)theMoney andRun;
-(void)take:(id)yourMedicine andDontComplain;
Perché Objective-C è stato progettato in questo modo? Era solo un artefatto di Smalltalk di cui nessuno vedeva la necessità di liberarsi?
Questa limitazione ha senso in Smalltalk, poiché Smalltalk non ha delimitatori attorno alla chiamata del messaggio, quindi il componente finale verrebbe interpretato come un messaggio unario all'ultimo argomento. Ad esempio, BillyAndBobby take:'$100' andRun
verrebbe analizzato come BillyAndBobby take:('$100' andRun)
. Questo non ha importanza in Objective-C dove sono richieste le parentesi quadre.
Supportare componenti selettori senza parametri non ci farebbe guadagnare molto in tutti i modi usuali in cui viene misurato un linguaggio, poiché il nome del metodo scelto da un programmatore (ad es. runWith:
Invece ditake:andRun
) non influenza la semantica funzionale di un programma, né l'espressività del linguaggio. In effetti, un programma con componenti senza parametri è alfa equivalente a uno senza. Non sono quindi interessato a risposte che affermano che una tale funzionalità non è necessaria (a meno che non fossero le ragioni dichiarate dei progettisti di Objective-C; qualcuno conosce Brad Cox o Tom Love? Sono qui?) O che dicono come scrivere i nomi dei metodi in modo che la funzionalità non sia necessaria. Il vantaggio principale è la leggibilità e la scrivibilità (che è come la leggibilità, solo ... sai), poiché significherebbe che potresti scrivere nomi di metodi che assomigliano ancora di più a frasi in linguaggio naturale. Artisti del calibro di -(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication
(che Matt Gallagher sottolinea in "Cocoa With Love"-(BOOL)application:(NSApplication*)theApplication shouldTerminateAfterLastWindowClosed
, ponendo così il parametro immediatamente accanto al nome appropriato.
Il runtime Objective-C di Apple (ad esempio) è perfettamente in grado di gestire questo tipo di selettori, quindi perché non il compilatore? Perché non supportarli anche nei nomi dei metodi?
#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;
}