Em Objective-C, você não pode declarar nomes de métodos onde o último componente não aceita um argumento. Por exemplo, o seguinte é ilegal.
-(void)take:(id)theMoney andRun;
-(void)take:(id)yourMedicine andDontComplain;
Por que Objective-C foi projetado dessa forma? Era apenas um artefato de Smalltalk do qual ninguém viu necessidade de se livrar?
Essa limitação faz sentido em Smalltalk, uma vez que Smalltalk não tem delimitadores em torno da invocação da mensagem, então o componente final seria interpretado como uma mensagem unária para o último argumento. Por exemplo, BillyAndBobby take:'$100' andRun
seria analisado como BillyAndBobby take:('$100' andRun)
. Isso não importa em Objective-C, onde colchetes são obrigatórios.
O suporte a componentes do seletor sem parâmetros não nos renderia muito em todas as formas usuais de uma linguagem é medida, como o nome do método que um programador escolhe (por exemplo, runWith:
em veztake:andRun
) não afeta a semântica funcional de um programa, nem a expressividade da linguagem. Na verdade, um programa com componentes sem parâmetros é alfa equivalente a um sem. Portanto, não estou interessado em respostas que afirmam que tal recurso não é necessário (a menos que seja essa a razão declarada dos designers de Objective-C; alguém conhece Brad Cox ou Tom Love? Eles estão aqui?) Ou que dizem como escrever nomes de métodos para que o recurso não seja necessário. O principal benefício é a legibilidade e a gravabilidade (que é como a legibilidade, só ... você sabe), pois isso significaria que você poderia escrever nomes de métodos que se assemelham ainda mais a sentenças de linguagem natural. Gostos de -(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication
(que Matt Gallagher aponta em "Cocoa With Love"-(BOOL)application:(NSApplication*)theApplication shouldTerminateAfterLastWindowClosed
, colocando assim o parâmetro imediatamente próximo ao substantivo apropriado.
O tempo de execução Objective-C da Apple (por exemplo) é perfeitamente capaz de lidar com esse tipo de seletores, então por que não o compilador? Por que não suportá-los em nomes de métodos também?
#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
e takeAndDon'tComplainAbout:(id)yourMedicine
. Gramaticamente estranho, com certeza.
- (void) :(id)theMoney;
ou - (void) :(id)obj1 :(id)obj2;
. Portanto, os seletores que consistem em nada além de dois pontos são adequados. ;-)