En Objective-C, vous ne pouvez pas déclarer de noms de méthode où le dernier composant ne prend pas d'argument. Par exemple, ce qui suit est illégal.
-(void)take:(id)theMoney andRun;
-(void)take:(id)yourMedicine andDontComplain;
Pourquoi Objective-C a-t-il été conçu de cette façon? Était-ce juste un artefact de Smalltalk dont personne ne voyait le besoin de se débarrasser?
Cette limitation a du sens dans Smalltalk, car Smalltalk n'a pas de délimiteurs autour de l'appel de message, donc le composant final serait interprété comme un message unaire jusqu'au dernier argument. Par exemple, BillyAndBobby take:'$100' andRun
serait analysé comme BillyAndBobby take:('$100' andRun)
. Cela n'a pas d'importance en Objective-C où les crochets sont obligatoires.
La prise en charge des composants de sélecteur sans paramètre ne nous rapporterait pas beaucoup de toutes les manières habituelles de mesurer un langage, comme le nom de méthode choisi par un programmeur (par exemple, runWith:
plutôt quetake:andRun
) n'affecte pas la sémantique fonctionnelle d'un programme, ni l'expressivité du langage. En effet, un programme avec des composants sans paramètres équivaut à un programme sans. Je ne suis donc pas intéressé par les réponses indiquant qu'une telle fonctionnalité n'est pas nécessaire (à moins que ce ne soit les raisons invoquées par les concepteurs d'Objective-C; est-ce que quelqu'un connaît Brad Cox ou Tom Love? Sont-ils ici?) Ou qui disent comment écrire des noms de méthode pour que la fonctionnalité ne soit pas nécessaire. Le principal avantage est la lisibilité et l'écriture (ce qui est comme la lisibilité, seulement ... vous savez), car cela signifierait que vous pourriez écrire des noms de méthodes qui ressemblent encore plus à des phrases en langage naturel. Les goûts de -(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication
(que Matt Gallagher souligne sur "Cocoa With Love"-(BOOL)application:(NSApplication*)theApplication shouldTerminateAfterLastWindowClosed
, plaçant ainsi le paramètre immédiatement à côté du nom approprié.
Le runtime Objective-C d'Apple (par exemple) est parfaitement capable de gérer ce type de sélecteurs, alors pourquoi pas le compilateur? Pourquoi ne pas les soutenir également dans les noms de méthodes?
#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
ettakeAndDon'tComplainAbout:(id)yourMedicine
. Grammaticalement maladroit, pour être sûr.- (void) :(id)theMoney;
ou- (void) :(id)obj1 :(id)obj2;
. Les sélecteurs composés uniquement de deux points conviennent donc. ;-)Réponses:
C'est Brad Cox. Ma réponse initiale a mal compris la question. J'ai supposé que reallyFast était une extension codée en dur pour déclencher une messagerie plus rapide, pas une sorte de sucre syntaxique. La vraie réponse est que Smalltalk ne l'a pas pris en charge, peut-être parce que son analyseur ne pouvait pas gérer l'ambiguïté (supposée). Bien que les crochets d'OC éliminent toute ambiguïté, je n'ai tout simplement pas pensé à m'éloigner de la structure des mots-clés de Smalltalk.
la source
21 ans de programmation Objective-C et cette question ne m'a jamais traversé l'esprit. Compte tenu de la conception du langage, le compilateur a raison et les fonctions d'exécution sont fausses ().
La notion d'arguments entrelacés avec des noms de méthode a toujours signifié que, s'il y a au moins un argument, le dernier argument est toujours la dernière partie de la syntaxe d'invocation de méthode.
Sans trop y réfléchir, je parierais qu'il y a des bugs syntaxiques avec la non-application du modèle actuel. Au moins, cela rendrait le compilateur plus difficile à écrire, car toute syntaxe qui a des éléments optionnels entrelacés avec des expressions est toujours plus difficile à analyser. Il pourrait même y avoir un boîtier de bord qui l'empêche complètement. Certes, Obj-C ++ le rendrait plus difficile, mais cela n'a été intégré au langage que des années après que la syntaxe de base ait déjà été gravée dans la pierre.
Quant à savoir pourquoi Objective-C a été conçu de cette façon, je soupçonne que la réponse est que les concepteurs originaux du langage n'ont tout simplement pas envisagé de permettre à la syntaxe entrelacée d'aller au-delà de ce dernier argument.
C'est une meilleure estimation. Je vais demander à l'un d'eux et mettre à jour ma réponse lorsque j'en saurai plus.
J'ai interrogé Brad Cox à ce sujet et il a été très généreux en répondant en détail (Merci, Brad !!):
Allez lire la réponse de Brad!
la source
-myObjectWithDelegate: (id) foo wantsYouToDoSomethingWith: (id) bar
. Cela conduit à une incohérence discordante dans les noms de méthode si vous avez une méthode dans le protocole qui n'a besoin d'aucun autre paramètre. Voir NSTableViewDataSource pour un exemple. Une méthode ne suit pas le joli schéma soigné de toutes les autres.Juste pour votre information, le runtime ne se soucie pas réellement des sélecteurs, toute chaîne C est valide, vous pouvez aussi faire un sélecteur comme ça: "== + === + ---__-- ¨¨¨¨ ¨ ^ :::::: "sans argument le runtime l'acceptera, le compilateur ne peut tout simplement pas ou bien il est impossible d'analyser. Il n'y a absolument aucun contrôle de cohérence en ce qui concerne les sélecteurs.
la source
Je suppose qu'ils ne sont pas pris en charge dans Objective-C car ils n'étaient pas non plus disponibles dans Smalltalk. Mais cela a une raison différente de celle que vous pensez: ils ne sont pas nécessaires. Ce qu'il faut, c'est la prise en charge des méthodes avec 0, 1, 2, 3, ... arguments. Pour chaque nombre d'arguments, il existe déjà une syntaxe fonctionnelle pour les appeler. L'ajout de toute autre syntaxe ne ferait que provoquer une confusion inutile.
Si vous vouliez des sélecteurs multi-mots sans paramètre, pourquoi vous arrêter avec un seul mot supplémentaire? On pourrait alors demander que
devient également supporté (c'est-à-dire qu'un sélecteur est une séquence de mots, certains avec deux-points et un paramètre, et d'autres non). Bien que cela aurait été possible, je suppose que personne ne l'a jugé utile.
la source
and
etor
serait des pierres d'achoppement particulières). Cela se produirait beaucoup moins si seul le composant final d'un nom de méthode était autorisé à ne pas avoir de paramètre, car il aurait tendance à être composé de plusieurs mots.