Когда здоровый программист впервые видит вызовы методов в Objective C — у него выпадают глаза.
Давай поговорим об этом.
Представь себе, что при вызове метода ты даешь человеческие названия каждому параметру. Сейчас это модно и обычно для этого в аргументе передается хэш:
Это очень удобно и наглядно в вызывающем коде; не нужно помнить параметры и порядок их передачи; не нужно плодить одинаковые методы на разный комплект параметров и так далее.
В Objective C создатели решили закрепить это правило на уровне синтаксиса языка: каждый параметр имеет название. Оно указывается как при вызове, так и при определении метода. Таким образом, жестко внедряется практика, когда программисту приходится думать над сутью вещей, а не просто дубасить код.
Но большое количество методов вызываются с единственным параметром. В этом случае, очевидно, не имеет смысла его отдельно именовать, т.к. из самого названия метода обычно все понятно.
Для этого случая в Objective C существует упрощенный синтаксис, который обычно и вводит в ступор новичков. Первый параметр метода названия не имеет. Вот так: все параметры названы, а первый — нет. В каком-нибудь из скриптовых языков это могло бы выглядеть, скажем, как-то так:
Я думаю, что это — самая главная проблема в постижении Objective C. Опытный программист интуитивно поймет логику практически любого языка программирования, но без вот этого «секретного знания» сходу разобраться в Objective C врядли можно.
Получился интересный побочный эффект. Уж не знаю, специально ли так задумано или исторически сложилось, но название первого параметра стали выносить в название метода.
Например:
А теперь — слайды.
Вызов метода в Objective C пишется в квадратных скобках. В начале идет переменная объекта. Затем — название метода и его параметр через двоеточие.
В других языках это могло бы выглядеть так:
А вот так выглядит само определение метода в замечательном объекте:
С минуса начинается определение метода объекта. В скобках — возвращаемый тип данных, указатель, как в C:
Внутри метода можно обращаться к переменной
В других языках это могло бы выглядеть так:
Теперь — последний и самый сложный шаг в понимании вопроса.
Вот так вызывается метод с двумя параметрами. Первый ("
Параметров может быть множество:
Внутри квадратных скобок — только вызов одного метода у одного объекта, не запутаешься.
В другом языке программирования это могло бы звучать так:
А вот так выглядит определение этого метода:
Точно также указывается минус, тип возвращаемых данных, название метода, тип и переменная первого параметра. Затем, через пробел — название следующего параметра, его тип и переменная. И так далее.
Важный момент. Внутри метода названия параметров не используются. Чтобы проиллюстрировать это, я назвал второй параметр
Но если ты захочешь обратишься к
Чаще всего названия переменных и параметров для простоты так и пишут одинаково.
И на десерт — ничего не возвращающий метод без параметров:
Вызов:
Определение:
Такой способ вызова методов, естественно, поначалу вызывает отторжение. Это нормально. Без секретного знания про первый параметр прочитать сходу код на Objective C невозможно, а это вызывает раздражение, причем даже больше у опытных программистов. А накопленное раздражение, в свою очередь, моментально ассоциируется с его источником.
Но если пойти правильным путем — разобраться и принять без боя — то эти и другие принципы становятся вполне родными и понятными. Objective C уже много лет разрабатывают отнюдь не глупые люди, и там нет принципиально неправильных вещей. Objective C по-своему прекрасен.
А опыт программирования на Objective C принесет в твою практику, среди всего прочего, новую культуру именования вещей. А от этого выйграет любой код на любом языке.
PS для опытных специалистов: это статья для начинающих. Поэтому я несколько утрировал смысл, чтобы сфокусироваться на главном. В частности, я не упомянул, как на самом деле называются методы и так далее.
Давай поговорим об этом.
Теория
Представь себе, что при вызове метода ты даешь человеческие названия каждому параметру. Сейчас это модно и обычно для этого в аргументе передается хэш:
PHP
$image
->calculateSize(array(
'image' => $image,
'width' => 50,
'height' => 50
));
Javascript
image
.calculateSize({
image: image,
width: 50,
height: 50
});
Это очень удобно и наглядно в вызывающем коде; не нужно помнить параметры и порядок их передачи; не нужно плодить одинаковые методы на разный комплект параметров и так далее.
В Objective C создатели решили закрепить это правило на уровне синтаксиса языка: каждый параметр имеет название. Оно указывается как при вызове, так и при определении метода. Таким образом, жестко внедряется практика, когда программисту приходится думать над сутью вещей, а не просто дубасить код.
Но большое количество методов вызываются с единственным параметром. В этом случае, очевидно, не имеет смысла его отдельно именовать, т.к. из самого названия метода обычно все понятно.
$records->storeData('sirko.db');
$users->findNickname('vasya');
Для этого случая в Objective C существует упрощенный синтаксис, который обычно и вводит в ступор новичков. Первый параметр метода названия не имеет. Вот так: все параметры названы, а первый — нет. В каком-нибудь из скриптовых языков это могло бы выглядеть, скажем, как-то так:
PHP
$this->calculateSize($image, array(
'width' => 50,
'height' => 50
));
JavaScript
image->calculateSize(image, {
width: 50,
height: 50
});
Я думаю, что это — самая главная проблема в постижении Objective C. Опытный программист интуитивно поймет логику практически любого языка программирования, но без вот этого «секретного знания» сходу разобраться в Objective C врядли можно.
Получился интересный побочный эффект. Уж не знаю, специально ли так задумано или исторически сложилось, но название первого параметра стали выносить в название метода.
Например:
findUserByNickname,
locateByCoordinates,
storeIntoFilename,
loadFromTable,
setupById
и так далее. Такая система именования здесь полностью прижилась, в результате чего код на Objective C в среднем неплохо читаемый.Практика
А теперь — слайды.
content = [answersTable findById:42];
Вызов метода в Objective C пишется в квадратных скобках. В начале идет переменная объекта. Затем — название метода и его параметр через двоеточие.
answersTable
— экземпляр какого-нибудь замечательного объекта, findById
— метод, а 42
— это хорошая цифра. Результат возвращается в переменную content.
Мнемоническое правило: квадратные скобки заменяются на вычисление содержимого. (Как в Tcl).В других языках это могло бы выглядеть так:
$content = $answersTable->findByid(42);
А вот так выглядит само определение метода в замечательном объекте:
- (AnswerContent *) findById: (int) questionId {
...
[self doSomething:questionId];
...
}
С минуса начинается определение метода объекта. В скобках — возвращаемый тип данных, указатель, как в C:
(AnswerContent *)
. Проще говоря, это значит, что метод вернет объект типа AnswerContent
. Далее идет название метода (findById
) и через двоеточие — переменная первого параметра, также с обязательным указанием ее типа, тоже как в C: (int) questionId
. Внутри метода можно обращаться к переменной
questionId.
В других языках это могло бы выглядеть так:
PHP
public function findById($questionId) {
...
$this->db->get($questionId);
...
}
JavaScript
Smth.prototype.findById = function(questionId) {
...
this.db.get(questionId);
...
}
Теперь — последний и самый сложный шаг в понимании вопроса.
masterpiece = [gallery findImageByWidth:400 andHeight:300];
Вот так вызывается метод с двумя параметрами. Первый ("
400
") названия не имеет, указывается сразу после имени метода. Второй имеет название: andHeight
. Обрати внимание, как элегантно назван метод и его параметры. Через некоторое время привыкаешь так писать и читать и проговариваешь про себя: «gallery, pls find image by width and height». Параметров может быть множество:
price = [trade calculateWithPrice:25.55 volume:500 value:3 ticker:aaplTicker];
Внутри квадратных скобок — только вызов одного метода у одного объекта, не запутаешься.
В другом языке программирования это могло бы звучать так:
PHP
$price = $trade->calculate(array(
'price' => 25.55,
'volume' => 500,
'value' => 3,
'ticker' => $aaplTicker
));
JavaScript
price = trade.calculate({
price: 25.55,
volume: 500,
value: 3,
ticker: aaplTicker
});
А вот так выглядит определение этого метода:
- (float) calculateWithPrice:(float)price volume:(int)volumeAmount
value:(int)value ticker:(TickerClass *)ticker {
...
}
Точно также указывается минус, тип возвращаемых данных, название метода, тип и переменная первого параметра. Затем, через пробел — название следующего параметра, его тип и переменная. И так далее.
Важный момент. Внутри метода названия параметров не используются. Чтобы проиллюстрировать это, я назвал второй параметр
volume,
но он помещается в переменную volumeAmount.
Внутри метода можно к ней обратиться: volumeAmount+=10;
Но если ты захочешь обратишься к
volume
— компилятор будет возражать, такой переменной не существует. А вот параметр с названием price
помещается в переменную с таким же названием. Все просто: price = price * 0.90; // a better discount for our customer
Чаще всего названия переменных и параметров для простоты так и пишут одинаково.
И на десерт — ничего не возвращающий метод без параметров:
Вызов:
[self destroy];
Определение:
- (void) destroy {
...
}
Выводы
Такой способ вызова методов, естественно, поначалу вызывает отторжение. Это нормально. Без секретного знания про первый параметр прочитать сходу код на Objective C невозможно, а это вызывает раздражение, причем даже больше у опытных программистов. А накопленное раздражение, в свою очередь, моментально ассоциируется с его источником.
Но если пойти правильным путем — разобраться и принять без боя — то эти и другие принципы становятся вполне родными и понятными. Objective C уже много лет разрабатывают отнюдь не глупые люди, и там нет принципиально неправильных вещей. Objective C по-своему прекрасен.
А опыт программирования на Objective C принесет в твою практику, среди всего прочего, новую культуру именования вещей. А от этого выйграет любой код на любом языке.
PS для опытных специалистов: это статья для начинающих. Поэтому я несколько утрировал смысл, чтобы сфокусироваться на главном. В частности, я не упомянул, как на самом деле называются методы и так далее.