W Objective-C nie można zadeklarować nazw metod, w których ostatni składnik nie przyjmuje argumentu. Na przykład poniższy kod jest niedozwolony.
-(void)take:(id)theMoney andRun;
-(void)take:(id)yourMedicine andDontComplain;
Dlaczego Objective-C został zaprojektowany w ten sposób? Czy to tylko artefakt Smalltalk, którego nikt nie widział potrzeby się pozbyć?
To ograniczenie ma sens w Smalltalk, ponieważ Smalltalk nie ma ograniczników wokół wywołania wiadomości, więc ostatni składnik byłby interpretowany jako jednoargumentowa wiadomość do ostatniego argumentu. Na przykład BillyAndBobby take:'$100' andRun
zostanie przeanalizowany jako BillyAndBobby take:('$100' andRun)
. Nie ma to znaczenia w Objective-C, gdzie wymagane są nawiasy kwadratowe.
Wspieranie komponentów selektora bez parametrów nie dałoby nam wiele we wszystkich typowych sposobach mierzenia języka, ponieważ nazwa metody, którą wybiera programista (np. runWith:
Zamiasttake:andRun
) nie wpływa na semantykę funkcjonalną programu ani na ekspresję języka. Rzeczywiście, program z komponentami bez parametrów jest alfa równoważny programowi bez. Dlatego nie interesują mnie odpowiedzi, które stwierdzają, że taka funkcja nie jest konieczna (chyba że takie były powody projektantów Objective-C; czy ktoś zdarzyło się znać Brada Coxa lub Toma Love? Czy oni tu są?) Lub które mówią jak pisać nazwy metod, aby funkcja nie była potrzebna. Podstawową zaletą jest czytelność i zapisywalność (co jest jak czytelność, tylko ... wiesz), ponieważ oznaczałoby to, że możesz pisać nazwy metod, które jeszcze bardziej przypominają zdania w języku naturalnym. Takie jak -(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication
(na co Matt Gallagher zwraca uwagę w „Cocoa With Love”-(BOOL)application:(NSApplication*)theApplication shouldTerminateAfterLastWindowClosed
, umieszczając w ten sposób parametr bezpośrednio obok odpowiedniego rzeczownika.
Środowisko uruchomieniowe Objective-C firmy Apple (na przykład) doskonale radzi sobie z tego rodzaju selektorami, więc dlaczego nie kompilator? Dlaczego nie wspierać ich również w nazwach metod?
#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
itakeAndDon'tComplainAbout:(id)yourMedicine
. Z pewnością gramatycznie niezręczny.- (void) :(id)theMoney;
lub- (void) :(id)obj1 :(id)obj2;
. Tak więc selektory składające się wyłącznie z dwukropków są w porządku. ;-)Odpowiedzi:
To jest Brad Cox. Moja pierwotna odpowiedź źle zrozumiała pytanie. Założyłem, że naprawdę Fast to zakodowane na stałe rozszerzenie uruchamiające szybsze przesyłanie wiadomości, a nie rodzaj cukru syntaktycznego. Prawdziwą odpowiedzią jest to, że Smalltalk go nie obsługiwał, być może dlatego, że jego parser nie radził sobie z (zakładaną) niejednoznacznością. Chociaż nawiasy kwadratowe w OC usunęłyby wszelkie niejasności, po prostu nie pomyślałem o odejściu od struktury słów kluczowych Smalltalka.
źródło
21 lat programowania Objective-C i to pytanie nigdy nie przyszło mi do głowy. Biorąc pod uwagę projekt języka, kompilator ma rację, a funkcje uruchomieniowe są nieprawidłowe ().
Pojęcie przeplatanych argumentów z nazwami metod zawsze oznaczało, że jeśli istnieje co najmniej jeden argument, ostatni argument jest zawsze ostatnią częścią składni wywołania metody.
Bez zastanawiania się nad tym strasznie dużo, założę się, że są pewne błędy składniowe, w których brak narzucania obecnego wzorca. Przynajmniej utrudniłoby to pisanie kompilatorowi, ponieważ każda składnia, która ma elementy opcjonalne przeplecione wyrażeniami, jest zawsze trudniejsza do przeanalizowania. Może nawet istnieć przypadek krawędzi, który płasko temu zapobiega. Z pewnością Obj-C ++ uczyniłby to trudniejszym, ale nie zostało to zintegrowane z językiem aż do lat po tym, jak podstawowa składnia została już ustalona.
Jeśli chodzi o powód, dla którego Objective-C został zaprojektowany w ten sposób, podejrzewam, że odpowiedź brzmi, że pierwotni projektanci języka po prostu nie rozważali dopuszczenia przeplatanej składni do wyjścia poza ten ostatni argument.
To najlepsze przypuszczenie. Zapytam jednego z nich i zaktualizuję odpowiedź, gdy dowiem się więcej.
Zapytałem o to Brada Coxa i był bardzo hojny w szczegółowej odpowiedzi (Dzięki, Brad !!):
Przeczytaj odpowiedź Brada!
źródło
-myObjectWithDelegate: (id) foo wantsYouToDoSomethingWith: (id) bar
. Prowadzi to do irytującej niespójności w nazwach metod, jeśli w protokole jest metoda, która nie wymaga innych parametrów. Aby zapoznać się z przykładem, zobacz NSTableViewDataSource. Jedna metoda nie jest zgodna z ładnym, schludnym wzorcem wszystkich innych.Tak dla twojej informacji, środowisko wykonawcze tak naprawdę nie dba o selektory, każdy łańcuch C jest prawidłowy, równie dobrze możesz stworzyć taki selektor: "== + === + ---__-- ¨¨¨¨ ¨ ^ :::::: "bez argumentu środowisko wykonawcze zaakceptuje to, kompilator po prostu nie może, albo nie można go przeanalizować. W przypadku selektorów nie ma absolutnie żadnej kontroli poczytalności.
źródło
Zakładam, że nie są obsługiwane w Objective-C, ponieważ nie były również dostępne w Smalltalk. Ale ma to inny powód niż myślisz: nie są potrzebne. Potrzebna jest obsługa metod z argumentami 0, 1, 2, 3, .... Dla każdej liczby argumentów istnieje już działająca składnia do ich wywoływania. Dodanie jakiejkolwiek innej składni po prostu spowodowałoby niepotrzebne zamieszanie.
Jeśli potrzebujesz selektorów wielowyrazowych bez parametrów, po co poprzestać na jednym dodatkowym słowie? Można by wtedy o to zapytać
również staje się obsługiwany (tj. że selektor jest sekwencją słów, niektóre z dwukropkiem i parametrem, a inne nie). Chociaż byłoby to możliwe, zakładam, że nikt nie uznał tego za warte zachodu.
źródło
and
ior
byłoby to szczególnymi przeszkodami). Byłoby to znacznie rzadziej, gdyby tylko ostatni składnik nazwy metody nie miał parametru, ponieważ składałby się z wielu słów.