Почему последняя часть имени метода Objective-C должна принимать аргумент (если имеется более одной части)? - PullRequest
89 голосов
/ 18 декабря 2010

В 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 (которые Мэтт Галлахер указывает на на «Какао с любовью» немного сбивает с толку, когда вы отбрасываете формальный параметр) могут быть названы -(BOOL)application:(NSApplication*)theApplication shouldTerminateAfterLastWindowClosed, таким образом поместив параметр непосредственно рядом с соответствующим существительным.

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

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

Ответы [ 4 ]

110 голосов
/ 20 декабря 2010

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

42 голосов
/ 19 декабря 2010

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

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

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

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

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

<Ч />

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

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

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

21 голосов
/ 19 декабря 2010

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

6 голосов
/ 18 декабря 2010

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

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

 [axolotl perform selector: Y with object: Y]

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

...