Почему последняя часть имени метода Objective-C принимает аргумент (когда имеется более одной части)?

В Objective-C вы не можете объявлять имена методов, где последний компонент не принимает аргумент. Например, следующее незаконно.

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

Почему был разработан Objective-C таким образом? Это был просто артефакт Smalltalk, от которого никто не видел, что нужно избавиться?

Это ограничение имеет смысл в Smalltalk, поскольку Smalltalk не имеет разделителей вокруг вызова сообщений, поэтому последний компонент будет интерпретироваться как унарное сообщение для последнего аргумента. Например, BillyAndBobby take:'$100' andRun будет анализироваться как BillyAndBobby take:('$100' andRun). Это не имеет значения в Objective-C, где требуются квадратные скобки.

Поддержка безпараллельных селекторных компонентов не принесет нам большого значения во всех обычных способах измерения языка, поскольку имя метода, которое выбирает программист (например, runWith:, а не take:andRun), не влияет на функциональную семантику программы или выразительности языка. Действительно, программа с безпараллельными компонентами альфа эквивалентна одной без. Я, таким образом, не интересуюсь ответами, в которых утверждается, что такая функция не нужна (если только это не было изложено в конструкторах Objective-C, кто-нибудь случайно знает Брэда Кокса или Тома Лава?) как писать имена методов, поэтому функция не нужна. Основное преимущество - читаемость и возможность записи (что похоже на читаемость, только... вы знаете), поскольку это означало бы, что вы могли бы писать имена методов, которые еще более напоминают предложения на языке естественного языка. Подобно -(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication (который Мэтт Галлахер указывает на "Cocoa With Love" немного запутанно, когда вы отбрасываете формальный параметр), можно назвать -(BOOL)application:(NSApplication*)theApplication shouldTerminateAfterLastWindowClosed, тем самым помещая параметр непосредственно рядом с соответствующим существительным.

Apple Objective-C runtime (например) отлично справляется с этими типами селекторов, так почему же не компилятор? Почему бы не поддержать их в именах методов?

#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

Это Брэд Кокс. Мой первоначальный ответ неправильно понял вопрос. Я предположил, что reallyFast был жестко запрограммированным расширением для запуска более быстрого обмена сообщениями, а не своего рода синтаксическим сахаром. Реальный ответ заключается в том, что Smalltalk не поддерживал его, возможно, потому, что его синтаксический анализатор не мог справиться с (предполагаемой) двусмысленностью. Хотя квадратные скобки OC устранили бы любую двусмысленность, я просто не думал о выходе из структуры ключевых слов Smalltalk.

Ответ 2

21 год программирования Objective-C, и этот вопрос никогда не приходил мне в голову. Учитывая конструкцию языка, компилятор прав, а функции выполнения неверны().

Понятие чередующихся аргументов с именами методов всегда означало, что если есть хотя бы один аргумент, последний аргумент всегда является последней частью синтаксиса вызова метода.

Не думая об этом через ужасно много, я бы поставил на то, что есть некоторые синтаксические бугабуки, не применяющие текущий шаблон. По крайней мере, это затруднило бы компилятор написать, что любой синтаксис, который имеет необязательные элементы, чередующиеся с выражениями, всегда сложнее анализировать. Там может быть даже краевой корпус, который предотвращает его. Конечно, Obj-С++ сделает его более сложным, но он не был интегрирован с языком до нескольких лет после того, как базовый синтаксис уже был установлен на камне.

Что касается того, почему Objective-C был спроектирован таким образом, я бы предположил, что ответ заключается в том, что оригинальные разработчики языка просто не рассматривали возможность синтаксиса с чередованием выйти за пределы последнего аргумента.

Это лучшее предположение. Я спрошу одного из них и уточню свой ответ, когда узнаю больше.


Я спросил Брэда Кокса об этом, и он был очень щедр, чтобы ответить подробно (спасибо, Брэд!!):

В то время я был сосредоточен на дублируя столько Smalltalk, сколько возможно в C и делать это как насколько это возможно. Любой запасной циклы стали обмен сообщениями быстро. Не было никакой мысли специализированной опции обмена сообщениями ( "reallyFast?" [ bbum: Я попросил использовать "doSomething: withSomething: reallyFast" как пример]), поскольку обычные сообщения были уже такими быстрыми, как они может быть. Это связано с ручной настройкой выход ассемблера C proto-messager, который был таким переносимость кошмара, что некоторые, если не все это было позже вывезено. я делаю Напомним, что взломанный вручную очень быстро; о стоимости двух вызовы функций; один, чтобы попасть в логика сообщений, а остальное - для поиск методов после этого.
Усовершенствования статической типизации были позже добавлено поверх Smalltalk pure динамическая типизация Стива Нароффа и другие. Я имел ограниченное участие в этом.

Забастовкa >

Прочитайте ответ Брэда!

Ответ 3

Только для вашей информации время выполнения на самом деле не заботится о селекторах, любая строка C действительна, вы также можете сделать селектор следующим образом: "== + === + ---__-- ¨ ¨¨¨¨¨¨ ^ ^::" без аргумента, что время выполнения примет его, компилятор просто не может или иначе это невозможно разобрать. В селекторах нет абсолютно никакой проверки на работоспособность.

Ответ 4

Я предполагаю, что они не поддерживаются в Objective-C, потому что они также недоступны в Smalltalk. Но это имеет другую причину, чем вы думаете: они не нужны. Нужна поддержка методов с аргументами 0, 1, 2, 3,.... Для каждого количества аргументов уже существует рабочий синтаксис для их вызова. Добавление любого другого синтаксиса просто вызовет ненужную путаницу.

Если вам нужны многословные селектора без параметров, зачем останавливаться на одном дополнительном слове? Тогда можно спросить, что

 [axolotl perform selector: Y with object: Y]

также поддерживается (т.е. что селектор представляет собой последовательность слов, некоторые с двоеточием и параметр, а другие нет). Хотя это было бы возможно, я предполагаю, что никто не считал это стоящим.