Perché l'ultima parte del nome di un metodo Objective-C deve accettare un argomento (quando è presente più di una parte)?


90

In Objective-C, non è possibile dichiarare nomi di metodi in cui l'ultimo componente non accetta un argomento. Ad esempio, quanto segue è illegale.

-(void)take:(id)theMoney andRun;
-(void)take:(id)yourMedicine andDontComplain;

Perché Objective-C è stato progettato in questo modo? Era solo un artefatto di Smalltalk di cui nessuno vedeva la necessità di liberarsi?

Questa limitazione ha senso in Smalltalk, poiché Smalltalk non ha delimitatori attorno alla chiamata del messaggio, quindi il componente finale verrebbe interpretato come un messaggio unario all'ultimo argomento. Ad esempio, BillyAndBobby take:'$100' andRunverrebbe analizzato come BillyAndBobby take:('$100' andRun). Questo non ha importanza in Objective-C dove sono richieste le parentesi quadre.

Supportare componenti selettori senza parametri non ci farebbe guadagnare molto in tutti i modi usuali in cui viene misurato un linguaggio, poiché il nome del metodo scelto da un programmatore (ad es. runWith:Invece ditake:andRun) non influenza la semantica funzionale di un programma, né l'espressività del linguaggio. In effetti, un programma con componenti senza parametri è alfa equivalente a uno senza. Non sono quindi interessato a risposte che affermano che una tale funzionalità non è necessaria (a meno che non fossero le ragioni dichiarate dei progettisti di Objective-C; qualcuno conosce Brad Cox o Tom Love? Sono qui?) O che dicono come scrivere i nomi dei metodi in modo che la funzionalità non sia necessaria. Il vantaggio principale è la leggibilità e la scrivibilità (che è come la leggibilità, solo ... sai), poiché significherebbe che potresti scrivere nomi di metodi che assomigliano ancora di più a frasi in linguaggio naturale. Artisti del calibro di -(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication(che Matt Gallagher sottolinea in "Cocoa With Love"-(BOOL)application:(NSApplication*)theApplication shouldTerminateAfterLastWindowClosed, ponendo così il parametro immediatamente accanto al nome appropriato.

Il runtime Objective-C di Apple (ad esempio) è perfettamente in grado di gestire questo tipo di selettori, quindi perché non il compilatore? Perché non supportarli anche nei nomi dei metodi?

#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;
}

1
non so spiegare il motivo per cui non è possibile, ma perché dovrebbe essere possibile? Apple chiamerebbe i metodi "takeAndRun:" e "takeAndDontComplain:";)

Oppure takeAndRunWith:(id)theMoneye takeAndDon'tComplainAbout:(id)yourMedicine. Grammaticamente imbarazzante, certo.
Matthew Frederick

13
Grazie per averlo chiesto: è una domanda molto interessante. Chiederò in giro.
bbum

5
È l'occasionale imbarazzo grammaticale forzato che mi fa desiderare la funzione.
outis

1
Ottima domanda. Per inciso, il compilatore non ha problemi con metodi denominati in questo modo: - (void) :(id)theMoney;o - (void) :(id)obj1 :(id)obj2;. Quindi i selettori composti da nient'altro che due punti vanno bene. ;-)
Ole Begemann

Risposte:


111

Questo è Brad Cox. La mia risposta originale ha frainteso la domanda. Ho pensato che reallyFast fosse un'estensione hardcoded per attivare messaggi più veloci, non una sorta di zucchero sintattico. La vera risposta è che Smalltalk non lo supportava, forse perché il suo parser non poteva gestire la (presunta) ambiguità. Sebbene le parentesi quadre di OC eliminassero qualsiasi ambiguità, semplicemente non pensavo di allontanarmi dalla struttura delle parole chiave di Smalltalk.


Grazie, Brad. La mia interpretazione della tua risposta è stata la stessa; quella partenza da SmallTalk non è stata considerata.
bbum

42

21 anni di programmazione di Objective-C e questa domanda non mi è mai passata per la mente. Dato il design del linguaggio, il compilatore ha ragione e le funzioni di runtime sono sbagliate ().

La nozione di argomenti interlacciati con nomi di metodo ha sempre significato che, se c'è almeno un argomento, l'ultimo argomento è sempre l'ultima parte della sintassi di invocazione del metodo.

Senza pensarci molto, scommetto che ci sono alcuni bugababoos sintattici che non applicano lo schema attuale. Per lo meno, renderebbe il compilatore più difficile da scrivere in quanto qualsiasi sintassi che ha elementi opzionali intercalati con espressioni è sempre più difficile da analizzare. Potrebbe anche esserci un caso limite che lo impedisce completamente. Certamente, Obj-C ++ lo avrebbe reso più impegnativo, ma non è stato integrato con il linguaggio fino ad anni dopo che la sintassi di base era già stata scolpita nella pietra.

Per quanto riguarda il motivo per cui Objective-C è stato progettato in questo modo, sospetto che la risposta sia che i progettisti originali del linguaggio non hanno semplicemente considerato di consentire alla sintassi interleaved di andare oltre l'ultimo argomento.

Questa è la migliore ipotesi. Chiederò a uno di loro e aggiornerò la mia risposta quando ne avrò di più.


Ho chiesto a Brad Cox di questo ed è stato molto generoso nel rispondere in dettaglio (Grazie, Brad !!):

In quel momento ero concentrato sulla duplicazione di quanto più Smalltalk possibile in C e su come farlo nel modo più efficiente possibile. Eventuali cicli di riserva sono stati necessari per rendere veloce la messaggistica ordinaria. Non si pensava a un'opzione di messaggistica specializzata ("reallyFast?" [ Bbum: ho chiesto usando 'doSomething: withSomething: reallyFast' come esempio ]) poiché i messaggi ordinari erano già veloci come potevano essere. Ciò ha comportato la messa a punto manuale dell'output dell'assemblatore del proto-messager C, che era un tale incubo di portabilità che alcuni, se non tutti, sono stati successivamente eliminati. Ricordo che il messaggero hackerato a mano era molto veloce; sul costo di due chiamate di funzione; uno per entrare nella logica del messaggero e il resto per fare ricerche di metodi una volta lì.
I miglioramenti alla digitazione statica sono stati successivamente aggiunti alla digitazione dinamica pura di Smalltalk da Steve Naroff e altri. Ho avuto solo un coinvolgimento limitato in questo.

Vai a leggere la risposta di Brad!


Gli errori di sintassi mi interessano molto.
outis

1
Mi sembra che se avessi una parte del nome del metodo senza due punti, hai un problema di analisi perché non puoi essere sicuro che sia destinato a far parte del nome del metodo o meno.
NSResponder

2
Mi è passato per la mente la prima volta che ho progettato un protocollo per un delegato che era molto meno di 21 anni dopo aver iniziato con Objective-C. Lo schema normale è fornire l'oggetto che invia il messaggio del delegato come primo parametro. es -myObjectWithDelegate: (id) foo wantsYouToDoSomethingWith: (id) bar. Ciò porta a un'incongruenza stridente nei nomi dei metodi se si dispone di un metodo nel protocollo che non necessita di altri parametri. Vedere NSTableViewDataSource per un esempio. Un metodo non segue il bel modello ordinato di tutti gli altri.
JeremyP

21

Solo per tua informazione, il runtime in realtà non si preoccupa dei selettori, qualsiasi stringa C è valida, potresti anche creare un selettore come questo: "== + === + ---__-- ¨¨¨¨ ¨ ^ :::::: "senza argomenti il ​​runtime lo accetterà, il compilatore semplicemente non può o è impossibile analizzarlo. Non ci sono assolutamente controlli di sanità mentale quando si tratta di selettori.


7
+1 Pensavo fossi totalmente pazzo per averlo suggerito, ma hai ragione. Per quelli di voi che non credono: pastie.org/1388361
Dave DeLong

6

Presumo che non siano supportati in Objective-C perché non erano disponibili nemmeno in Smalltalk. Ma questo ha un motivo diverso da quello che pensi: non sono necessari. Ciò che è necessario è il supporto per metodi con 0, 1, 2, 3, ... argomenti. Per ogni numero di argomenti, esiste già una sintassi funzionante per chiamarli. L'aggiunta di qualsiasi altra sintassi causerebbe solo una confusione non necessaria.

Se volevi selettori multi-parola senza parametri, perché fermarti con una sola parola in più? Uno potrebbe allora chiederlo

 [axolotl perform selector: Y with object: Y]

diventa anche supportato (cioè che un selettore è una sequenza di parole, alcune con due punti e un parametro e altre no). Anche se questo sarebbe stato possibile, presumo che nessuno lo considerasse utile.


1
Avevo pensato all'argomento "non servono", ma non mi interessava. La domanda aggiornata lo rende più chiaro. Consentire ai componenti del selettore arbitrario di non accettare parametri offre meno in termini di scrivibilità, poiché la differenza tra gli spazi e il case del cammello è inferiore alla differenza tra un componente finale senza parametri e la riscrittura di dichiarazioni in linguaggio naturale e parametri di riposizionamento (entrambi devono essere eseguiti con ObjC, così com'è).
uscita il

Inoltre, consentire componenti arbitrari senza parametri aumenta la possibilità di conflitti di parole chiave e complica la risoluzione dei nomi, specialmente quando si combinano C ++ e ObjC ( ande orsarebbero particolari ostacoli). Ciò accadrebbe molto meno se solo al componente finale del nome di un metodo fosse consentito di non avere parametri, poiché tenderebbe a consistere in più parole.
uscita il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.