В 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;
}
takeAndRunWith:(id)theMoney
иtakeAndDon'tComplainAbout:(id)yourMedicine
. Конечно, грамматически неудобно.- (void) :(id)theMoney;
или- (void) :(id)obj1 :(id)obj2;
. Так что селекторы, состоящие только из двоеточий, подходят. ;-)Ответы:
Это Брэд Кокс. Мой первоначальный ответ неправильно понял вопрос. Я предположил, что действительноFast - это жестко запрограммированное расширение для ускорения обмена сообщениями, а не синтаксический сахар. Настоящий ответ заключается в том, что Smalltalk не поддерживал его, возможно, потому, что его парсер не мог справиться с (предполагаемой) двусмысленностью. Хотя квадратные скобки OC устраняют любую двусмысленность, я просто не думал об отходе от структуры ключевых слов Smalltalk.
источник
21 год программирования Objective-C, и этот вопрос никогда не приходил мне в голову. Учитывая дизайн языка, компилятор правильный, а функции времени выполнения - неправильные ().
Понятие чередующихся аргументов с именами методов всегда означало, что, если есть хотя бы один аргумент, последний аргумент всегда является последней частью синтаксиса вызова метода.
Не вдаваясь в подробности, я готов поспорить, что есть некоторые синтаксические ошибки, в которых не применяется текущий шаблон. По крайней мере, это затруднило бы написание компилятора, поскольку любой синтаксис, в котором есть необязательные элементы, чередующиеся с выражениями, всегда труднее анализировать. Может быть, даже крайний корпус, который не позволяет этому. Конечно, Obj-C ++ усложнит задачу, но это не было интегрировано с языком до тех пор, пока не был установлен базовый синтаксис.
Что касается того, почему Objective-C был разработан таким образом, я подозреваю, что ответ заключается в том, что первоначальные разработчики языка просто не рассматривали возможность использования чередующегося синтаксиса за пределами этого последнего аргумента.
Это лучшее предположение. Я спрошу одного из них и обновлю свой ответ, когда узнаю больше.
Я спросил об этом Брэда Кокса, и он очень щедро ответил (Спасибо, Брэд !!):
Иди, прочитай ответ Брэда!
источник
-myObjectWithDelegate: (id) foo wantsYouToDoSomethingWith: (id) bar
. Это приводит к резкой несогласованности в именах методов, если у вас есть метод в протоколе, которому не нужны другие параметры. См. Пример NSTableViewDataSource. Один метод не следует красивому аккуратному шаблону всех остальных.Просто для вашего сведения, среда выполнения на самом деле не заботится о селекторах, допустима любая строка C, вы также можете создать такой селектор: "== + === + ---__-- ¨¨¨¨ ¨ ^ :::::: "без аргументов среда выполнения примет его, компилятор просто не может, иначе его невозможно проанализировать. Когда дело доходит до селекторов, здесь нет абсолютно никакой проверки.
источник
Я предполагаю, что они не поддерживаются в Objective-C, потому что они также не были доступны в Smalltalk. Но на то есть другая причина, чем вы думаете: они не нужны. Что необходимо, так это поддержка методов с 0, 1, 2, 3, ... аргументами. Для каждого количества аргументов уже существует рабочий синтаксис для их вызова. Добавление любого другого синтаксиса только вызовет ненужную путаницу.
Если вам нужны селекторы без параметров, состоящие из нескольких слов, зачем останавливаться на одном дополнительном слове? Тогда можно спросить, что
также становится поддерживаемым (т.е. селектор представляет собой последовательность слов, некоторые из которых имеют двоеточие и параметр, а другие нет). Хотя это было бы возможно, я полагаю, что никто не считал это стоящим.
источник
and
и этоor
может быть определенным камнем преткновения). Это произошло бы гораздо реже, если бы только последний компонент имени метода не имел параметров, так как он обычно состоял бы из нескольких слов.