En Objective-C, no puede declarar nombres de métodos donde el último componente no toma un argumento. Por ejemplo, lo siguiente es ilegal.
-(void)take:(id)theMoney andRun;
-(void)take:(id)yourMedicine andDontComplain;
¿Por qué Objective-C fue diseñado de esta manera? ¿Era solo un artefacto de Smalltalk del que nadie vio la necesidad de deshacerse?
Esta limitación tiene sentido en Smalltalk, ya que Smalltalk no tiene delimitadores alrededor de la invocación de mensajes, por lo que el componente final se interpretaría como un mensaje unario para el último argumento. Por ejemplo, BillyAndBobby take:'$100' andRun
se analizaría como BillyAndBobby take:('$100' andRun)
. Esto no importa en Objective-C, donde se requieren corchetes.
Admitir componentes de selector sin parámetros no nos beneficiaría mucho en todas las formas habituales en que se mide un lenguaje, ya que el nombre del método que elige un programador (por ejemplo, en runWith:
lugar detake:andRun
) no afecta la semántica funcional de un programa, ni la expresividad del lenguaje. De hecho, un programa con componentes sin parámetros es alfa equivalente a uno sin ellos. Por lo tanto, no me interesan las respuestas que indiquen que tal característica no es necesaria (a menos que esas fueran las razones declaradas por los diseñadores de Objective-C; ¿alguien conoce a Brad Cox o Tom Love? ¿Están aquí?) O que digan cómo escribir nombres de métodos para que la función no sea necesaria. El beneficio principal es la legibilidad y la capacidad de escritura (que es como la legibilidad, solo ... ya sabes), ya que significaría que podrías escribir nombres de métodos que se parezcan aún más a las oraciones del lenguaje natural. Los gustos de -(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication
(que Matt Gallagher señala en "Cocoa With Love"-(BOOL)application:(NSApplication*)theApplication shouldTerminateAfterLastWindowClosed
, colocando así el parámetro inmediatamente al lado del sustantivo apropiado.
El tiempo de ejecución Objective-C de Apple (por ejemplo) es perfectamente capaz de manejar este tipo de selectores, así que ¿por qué no el compilador? ¿Por qué no apoyarlos también en los nombres de los métodos?
#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;
}