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;
}
takeAndRunWith:(id)theMoney
ytakeAndDon'tComplainAbout:(id)yourMedicine
. Gramaticalmente incómodo, sin duda.- (void) :(id)theMoney;
o- (void) :(id)obj1 :(id)obj2;
. Por lo tanto, los selectores que solo contengan dos puntos están bien. ;-)Respuestas:
Este es Brad Cox. Mi respuesta original entendió mal la pregunta. Asumí que realmenteFast era una extensión codificada para activar mensajes más rápidos, no una especie de azúcar sintáctico. La respuesta real es que Smalltalk no lo admitió, quizás porque su analizador no pudo lidiar con la ambigüedad (supuesta). Aunque los corchetes de OC eliminarían cualquier ambigüedad, simplemente no pensé en apartarme de la estructura de palabras clave de Smalltalk.
fuente
21 años de programación de Objective-C y esta pregunta nunca se me ha pasado por la cabeza. Dado el diseño del lenguaje, el compilador tiene razón y las funciones en tiempo de ejecución son incorrectas ().
La noción de argumentos intercalados con nombres de métodos siempre ha significado que, si hay al menos un argumento, el último argumento es siempre la última parte de la sintaxis de invocación del método.
Sin pensarlo mucho, apuesto a que hay algunos errores sintácticos con no hacer cumplir el patrón actual. Al menos, haría que el compilador fuera más difícil de escribir, ya que cualquier sintaxis que tenga elementos opcionales intercalados con expresiones siempre es más difícil de analizar. Incluso podría haber un caso de borde que lo impida. Ciertamente, Obj-C ++ lo haría más desafiante, pero eso no se integró con el lenguaje hasta años después de que la sintaxis base ya estuviera escrita en piedra.
En cuanto a por qué Objective-C se diseñó de esta manera, sospecho que la respuesta es que los diseñadores originales del lenguaje simplemente no consideraron permitir que la sintaxis intercalada vaya más allá de ese último argumento.
Esa es la mejor suposición. Le preguntaré a uno de ellos y actualizaré mi respuesta cuando sepa más.
Le pregunté a Brad Cox sobre esto y fue muy generoso al responder en detalle (¡Gracias, Brad!):
¡Ve a leer la respuesta de Brad!
fuente
-myObjectWithDelegate: (id) foo wantsYouToDoSomethingWith: (id) bar
. Esto conduce a una discordancia discordante en los nombres de los métodos si tiene un método en el protocolo que no necesita otros parámetros. Consulte NSTableViewDataSource para ver un ejemplo. Un método no sigue el patrón ordenado y agradable de todos los demás.Solo para su información, al tiempo de ejecución no le importan los selectores, cualquier cadena C es válida, también podría hacer un selector como ese: "== + === + ---__-- ¨¨¨¨ ¨ ^ :::::: "sin argumento, el tiempo de ejecución lo aceptará, el compilador simplemente no puede o es imposible analizarlo. No hay absolutamente ningún control de cordura cuando se trata de selectores.
fuente
Supongo que no son compatibles con Objective-C porque tampoco estaban disponibles en Smalltalk. Pero eso tiene una razón diferente a la que cree: no son necesarios. Lo que se necesita es soporte para métodos con 0, 1, 2, 3, ... argumentos. Para cada número de argumentos, ya existe una sintaxis funcional para llamarlos. Agregar cualquier otra sintaxis solo causaría una confusión innecesaria.
Si deseaba selectores sin parámetros de varias palabras, ¿por qué detenerse con una sola palabra adicional? Entonces uno podría preguntar eso
también se admite (es decir, que un selector es una secuencia de palabras, algunas con dos puntos y un parámetro, y otras no). Si bien esto hubiera sido posible, supongo que nadie consideró que valiera la pena.
fuente
and
yor
serían obstáculos particulares). Esto sucedería mucho menos si solo se permitiera que el componente final de un nombre de método no tuviera parámetro, ya que tendería a constar de varias palabras.