In Objective-C können Sie keine Methodennamen deklarieren, bei denen die letzte Komponente kein Argument akzeptiert. Zum Beispiel ist Folgendes illegal.
-(void)take:(id)theMoney andRun;
-(void)take:(id)yourMedicine andDontComplain;
Warum wurde Objective-C so konzipiert? War es nur ein Artefakt von Smalltalk, das niemand für nötig hielt, um es loszuwerden?
Diese Einschränkung ist in Smalltalk sinnvoll, da Smalltalk keine Begrenzer für den Nachrichtenaufruf hat, sodass die letzte Komponente als unäre Nachricht zum letzten Argument interpretiert wird. Zum Beispiel BillyAndBobby take:'$100' andRun
würde analysiert werden als BillyAndBobby take:('$100' andRun)
. Dies spielt in Objective-C keine Rolle, wo eckige Klammern erforderlich sind.
Die Unterstützung parameterloser Auswahlkomponenten würde uns nicht auf die übliche Weise, wie eine Sprache gemessen wird, viel bringen, wie der Methodenname, den ein Programmierer auswählt (z. B. runWith:
anstatttake:andRun
) beeinflusst weder die funktionale Semantik eines Programms noch die Ausdruckskraft der Sprache. In der Tat ist ein Programm mit parameterlosen Komponenten Alpha-Äquivalent zu einem ohne. Ich bin daher nicht an Antworten interessiert, die besagen, dass eine solche Funktion nicht erforderlich ist (es sei denn, dies waren die angegebenen Gründe der Objective-C-Designer; kennt jemand Brad Cox oder Tom Love? Sind sie hier?) Oder diese sagen wie man Methodennamen schreibt, damit die Funktion nicht benötigt wird. Der Hauptvorteil ist die Lesbarkeit und Schreibbarkeit (was nur Lesbarkeit entspricht ... Sie wissen), da dies bedeuten würde, dass Sie Methodennamen schreiben könnten, die Sätzen in natürlicher Sprache noch ähnlicher sind. Ähnliches -(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication
(worauf Matt Gallagher in "Cocoa With Love" hinweist-(BOOL)application:(NSApplication*)theApplication shouldTerminateAfterLastWindowClosed
Dadurch wird der Parameter unmittelbar neben dem entsprechenden Substantiv platziert.
Die Objective-C-Laufzeit von Apple (zum Beispiel) kann diese Art von Selektoren perfekt verarbeiten. Warum also nicht den Compiler? Warum unterstützen Sie sie nicht auch in Methodennamen?
#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;
}
takeAndRunWith:(id)theMoney
und takeAndDon'tComplainAbout:(id)yourMedicine
. Grammatisch umständlich, um sicher zu sein.
- (void) :(id)theMoney;
oder - (void) :(id)obj1 :(id)obj2;
. Selektoren, die nur aus Doppelpunkten bestehen, sind also in Ordnung. ;-)