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
etakeAndDon'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. ;-)Respostas:
Este é o Brad Cox. Minha resposta original entendeu mal a pergunta. Eu presumi que realmenteFast fosse uma extensão codificada para acionar mensagens mais rápidas, não um tipo de açúcar sintático. A verdadeira resposta é que Smalltalk não o suportava, talvez porque seu analisador não pudesse lidar com a ambigüidade (assumida). Embora os colchetes do OC eliminassem qualquer ambigüidade, simplesmente não pensei em me afastar da estrutura de palavras-chave de Smalltalk.
fonte
21 anos programando Objective-C e essa questão nunca me passou pela cabeça. Dado o design da linguagem, o compilador está certo e as funções de tempo de execução estão erradas ().
A noção de argumentos intercalados com nomes de métodos sempre significou que, se houver pelo menos um argumento, o último argumento é sempre a última parte da sintaxe de invocação do método.
Sem pensar muito sobre isso, aposto que existem alguns problemas sintáticos em não impor o padrão atual. No mínimo, tornaria o compilador mais difícil de escrever, pois qualquer sintaxe que tenha elementos opcionais intercalados com expressões é sempre mais difícil de analisar. Pode até haver um caso extremo que evite isso. Certamente, Obj-C ++ o tornaria mais desafiador, mas ele não foi integrado à linguagem até anos depois que a sintaxe básica já estava gravada em pedra.
Quanto ao motivo pelo qual Objective-C foi projetado dessa forma, eu suspeito que a resposta é que os designers originais da linguagem simplesmente não consideraram permitir que a sintaxe intercalada fosse além do último argumento.
Esse é o melhor palpite. Vou perguntar a um deles e atualizar minha resposta quando descobrir mais.
Perguntei a Brad Cox sobre isso e ele foi muito generoso em responder detalhadamente (Obrigado, Brad !!):
Vá ler a resposta de Brad!
fonte
-myObjectWithDelegate: (id) foo wantsYouToDoSomethingWith: (id) bar
. Isso leva a uma inconsistência gritante nos nomes dos métodos se você tiver um método no protocolo que não precise de outros parâmetros. Veja NSTableViewDataSource para um exemplo. Um método não segue o padrão limpo e agradável de todos os outros.Apenas para sua informação, o tempo de execução não se preocupa realmente com os seletores, qualquer string C é válida, você também pode fazer um seletor como este: "== + === + ---__-- ¨¨¨¨ ¨ ^ :::::: "sem nenhum argumento o tempo de execução irá aceitá-lo, o compilador simplesmente não pode ou então é impossível analisar. Não há absolutamente nenhuma verificação de sanidade quando se trata de seletores.
fonte
Presumo que eles não sejam suportados em Objective-C porque também não estavam disponíveis em Smalltalk. Mas isso tem um motivo diferente do que você pensa: eles não são necessários. O que é necessário é o suporte para métodos com 0, 1, 2, 3, ... argumentos. Para cada número de argumentos, já existe uma sintaxe de trabalho para chamá-los. Adicionar qualquer outra sintaxe apenas causaria confusão desnecessária.
Se você queria seletores sem parâmetros com várias palavras, por que parar com uma única palavra extra? Pode-se então perguntar que
também se torna compatível (ou seja, um seletor é uma sequência de palavras, algumas com dois pontos e um parâmetro, e outras não). Embora isso tivesse sido possível, presumo que ninguém considerou que valesse a pena.
fonte
and
eor
seriam obstáculos específicos). Isso aconteceria muito menos se apenas o componente final de um nome de método não tivesse nenhum parâmetro, pois tenderia a consistir em várias palavras.