Часть пятая, все ещё Objective...
(Продолжение. Начало в №30)
В прошлый и позапрошлый разы мы успели достаточно подробно обсудить некоторые особенности главного языка программирования для этой платформы - Objective C. Сегодня продолжим разговор о нём.
Немного лирики
Для того, чтобы немного простимулировать вас к изучению обсуждаемого нами сейчас языка программирования, позволю себе сделать небольшое лирическое отступление о том, насколько в последнее время улучшились позиции Objective-C, по сравнению с другими языками программирования.
Не секрет, что периодически разные эксперты составляют рейтинги наиболее популярных в мире языков программирования. Одним из самых известных среди подобных рейтингов является "топ", составляемый компанией TIOBE Software. Конечно, в этом рейтинге Objective-C по-прежнему занимает не самые высокие места, но в данном случае главное - тенденция. Для языка программирования, который раньше вообще не попадал в ТОП-20, позиция в самом начале второй десятки - очень неплохой результат, который говорит о том, насколько сильно "айфономания" подогрела интерес к Objective-C. Судя по тому, какой интерес испытывает публика к iPhone 4, дальше позиции Objective-C будут расти еще быстрее, а это означает, что специалисты, владеющие этим языком программирования, будут востребованы всё больше и больше. Так что изучение Objective-C - это вложение сил и времени в светлое завтра востребованного программиста.
И всё-таки, Objective-C...
Что ж, после такого ободряющего вступления можно продолжить разговор об Objective-C. Я тут, кстати, как раз подумал, что, несмотря на то, что мы разговариваем о написании приложений для iPhone достаточно давно, да и о главном языке программирования для этой платформы, в общем-то, уже тоже, как такового кода на Objective-C мы еще не рассматривали. Впрочем, еще не поздно это исправить, поэтому сейчас предлагаю взглянуть на листинг, в котором приведен код достаточно простого класса, иллюстрирующий особенности того языка программирования, о котором мы с вами ведем разговор.
#import "Rect.h" @implementation Rect + newRect { Rect * rect = [[Rect alloc] init]; [rect setWidth: 1.0f]; [rect setHeight: 1.0f]; [rect setX: 0.0f y: 0.0f]; return rect; } - (float) width { return width; } - (float) height { return height; } - (float) area { return [self width] * [self height]; } - (void) setWidth: (float) theWidth { width = theWidth; } - (void) setHeight: (float) theHeight { height = theHeight; } - (void) setX: (float) theX y: (float) theY { x = theX; y = theY; } @end
Наверное, слишком уж подробно обсуждать здесь особо нечего, однако, думаю, стоит отметить несколько моментов. Обратите внимание, что, как и в случае с C++, мы можем задавать область видимости полей внутри класса. Также обратите внимание, что это все применимо только к полям - видимостью методов в Objective-C управлять, к сожалению, нельзя.
Вы также наверняка обратили внимание на то обстоятельство, что все описания методов в приведенном примере начинаются со знаков "плюс" или "минус". В общем-то, ничего особенно странного и загадочного в этом нет: плюсами помечаются методы классов (т.е. статические методы, относящиеся не к конкретному экземпляру данного класса, а ко всему классу в целом), а минусами как раз обозначаются методы объектов, то есть, экземпляров данного конкретного класса. Здесь, кстати говоря, стоит упомянуть еще одну крайне интересную особенность Objective-C: все методы в нем по определению являются виртуальными, то есть могут быть переопределены безо всяких дополнительных модификаторов в своих объявлениях. Это, кстати, тоже являются частью той самой гибкости этого языка программирования, о которой я так подробно рассказывал в самом начале.
Обратите также внимание на достаточно необычную для большинства компилируемых языков программирования ситуацию, когда можно не указывать тип возвращаемого методом значения, - по умолчанию считается, что оно имеет тип id, то есть является произвольным объектом. Нужно сказать также, что модель посылки сообщений объектам позволяет реализовывать методы, имеющие произвольное число параметров, - тоже не совсем обычно для компилируемых языков. Выглядит на практике такой метод примерно следующим образом (без кавычек, конечно): "- someMethod: (id) object, ...;".
Многопоточность и синхронизация
Может, конечно, вопрос создания многопоточных приложений действительно не такой уж и злободневный для тех, кто планирует писать приложения под iPhone, но, тем не менее, не рассказать о возможностях Objective-C в плане работы с несколькими потоками было бы, по меньшей мере, не вполне правильно. Так что мы с вами все-таки обсудим многопоточное программирование средствами Objective-C.
Заранее скажу, что изобретать велосипед создатели языка не стали, и те методы, которые применяются для синхронизации потоков, в Objective-C не отличаются особой новизной и оригинальностью. Для организации доступа потоков к критической секции кода используются старые добрые мьютексы, проверенные временем и выручившие не одно поколение программистов. Для работы с "однопоточным" кодом используется специальная директива @synchronized. При входе потока в защищенный такой директивой код проверяется, занят ли он уже каким-либо другим потоком или нет. В случае, если он все-таки занят, производится проверка мьютексов, которые используются потоками для входа в защищаемую директивой @synchronized область. Если указатели на эти объекты совпадают, то поток, который еще не вошел в защищаемый код, будет ждать, пока отработает его конкурент, а после того, как тот закончит свою работу, уже дождавшийся своей очереди поток закроет синхронизируемую область от всех остальных потоков.
В общем-то, еще раз повторюсь, вряд ли вам на первых порах понадобится работать с потоками при написании программ под iPhone, но, в любом случае, думаю, будет совсем не лишним иметь в виду наличие такой возможности, потому что популярность "обычной" Mac OS X, при программировании под которую работа с несколькими потоками будет совсем не лишней, заставляет сегодня разработчиков реализовывать версии своих приложений, написанных изначально под Windows, для этой операционной системы. Так что знание Objective-C будет полезно еще и с этой точки зрения.
Ещё немного о работе с объектами
Хотя мы с вами обсудили уже очень многое из того, что я хотел рассказать об особенностях языка, стоит остановиться еще на нескольких интересных моментах. Например, на так называемых категориях - механизме добавления новых методов к уже написанным кем-то ранее классам, дающим возможность всем классам-потомкам получать доступ к этим методам. Нужно сказать, что категории - это достаточно простой, по своей сути, но при этом мощный механизм, который позволяет добавлять свои методы к любому классу, в том числе и к базовому для всех остальных классов NSObjetc'у. Таким образом, методы, которые вы добавите к этому классу, станут доступны вообще всем классам без исключения.
При работе с объектами достаточно часто может понадобиться скопировать какой-либо объект. Специально для этого в Objective-C существуют специальные средства, позволяющие делать два вида копий объектов. Один вид - это так называемые "легкие" копии, то есть копии, которые сами по себе не содержат данных, а несут внутри себя только ссылку на объект с данными. Второй вид копирования - полное, или глубокое. В этом случае уже объект копируется вместе со всеми данными, которые он в себе содержит. Для копирования используется протокол NSCopying из стандартной рантайм-библиотеки производства Apple.
Источники для изучения Objective-C
Конечно, по нескольким газетным статьям достаточно сложно (мягко говоря) изучить целый язык программирования, особенно такой, как Objective-C. Поэтому вам, конечно, потребуется обратиться к некоторым более существенным источникам знаний, таким, как онлайн-ресурсы или книги. К счастью, сегодня уже достаточно много русскоязычных источников для тех, кто желает изучить этот язык программирования, хотя, конечно, для того, чтобы овладеть им в полной мере, без англоязычных тоже не обойтись.
Если вы предпочитаете изучать языки по русскоязычным книгам, то вам стоит обратиться к пособию "Objective-C 2.0 и программирование для Mac. Учебник и примеры", авторами которого являются Марк Далримпл и Скотт Кнастер. Конечно, сегодня компьютерная литература не относится к разряду очень дешевых, но это можно рассматривать как инвестиции в личный рост... Да и потом, если вы вдруг решите приобрести для разработки сам iPhone и компьютер производства Apple, то на фоне их стоимости цена книги уже вряд ли будет смотреться внушительно.
Если говорить о разработке именно под iPhone (а о ней мы сейчас и говорим), то здесь можно порекомендовать книги "iPhone SDK. Разработка приложений" и "iPhone. Разработка приложений с открытым кодом" Джонатана Здзиарски.
Что касается сетевых русскоязычных источников, то начать можно, например, с pyobjc.ru/2008/07/19/vvedenie-v-objective-c. А так, конечно, как говорится, Гугл в помощь. Это же касается и англоязычных ресурсов по Objective-C, которых в последнее время по вполне понятным причинам становится всё больше и больше. Ну и самое главное, конечно, помнить, что никакие книги и статьи не избавят вас от необходимости практиковаться в написании кода на Objective-C (желательно, конечно же, именно под iPhone).
Вадим СТАНКЕВИЧ,
dreamdrusch@tut.by
Комментарии
- (void) setX: (float) theX y: (float) theY
{
x = theX;
y = theY;
}
Вопрос - как называется этот "метод"? setX: ? - Допустим, то есть, в переводе на Java, вызов типа:
rect.setX(X, Y)
Не странно ли, назвать метод setX:, а устанавливает и X и Y?
Откинем "методы", а для понимания будем использовать "посылка сообщений", тогда, - что описывает вышеприведенный код - он описывает ОБРАБОТЧИК сообщения, или ТЕЛО МЕТОДА ОБРАБОТЧИКА сообщения. - Как называется этот МЕТОД ОБРАБОТЧИКА сообщения? - ответ - НЕ ИМЕЕТ значения!
А что имеет значение - а то, КАКОЙ ТИП(вид) сообщения обрабатывает данный обработчик сообщения? - Ответ, данный обработчик сообщения обрабатывает сообщение типа: "setX: y:" и ТОЛЬКО ЕГО!
Нюансы:
Как послать это сообщение объекту типа Rect? - в коде у СТАНКЕВИЧа это приведено:
[rect setX: 0.0f y: 0.0f];
Как можно описать это через понятие "метод"? - Типа так, у объекта типа rect вызывается метод setX: с параметрами, первый параметр метода setX: безымянный(!!!) и равен 0.0f, второй параметр метода setX: имеет имя y: и равен 0.0f. - Круто?! Мозги НЕ поломали ещё? ;-)
А теперь опишем тоже, через понятие "посылка сообщений": Типа так, объекту типа rect посылается сообщение "setX: y:" имеющее два параметра, первый параметр иммет имя setX: и значение 0.0f, второй параметр имеет имя y: и значение 0.0f. - Отлично, - И мозги устаканились! ;-)
Вообще, сообщение "setX: y:" лучше бы назвать(для понимания) - "setX: setY:" и вызывать как:
[rect setX: 0.0f setY: 0.0f];
А еще лучше (для понятливости) - назвать: "X: Y:" и вызывать как:
[rect X: 0.0f Y: 0.0f];
А код обработчика этого сообщения определить как:
- (void) X: (float) X Y: (float) Y
{
x = X;
y = Y;
}
Почему так? - Дело в том, что если написать так:
- (void) setX: (float) X setY: (float) Y
{
x = X;
y = Y;
}
То setX и setY - это имена(!) параметров сообщения, а X и Y - это переменные куда помещаются значение(!) этих параметров, - в теле обработчика нельзя использовать имена параметров, а можно только имена переменных куда помещаются значение этих параметров. Для того, чтобы не "спотыкаться", часто пишут например так:
- (void) amount: (int) amount price: (int) price
{
summa = amount * price;
}
А посылают сообщение так( тут kassa - объект определённого типа, который может обрабатывать сообщения типа "amount: price:"):
[kassa amount: 2 price: 500];
А если же определить обработчик этого сообщения как:
- (void) amount: (int) valueAmount price: (int) valuePrice
{
summa = amount * price;
}
То посылать сообщение можно так же:
[kassa amount: 2 price: 500];
А вот компилятор(!) в этом случае выдаст ошибку, ибо нет таких переменных для него как amount и price, а есть переменные valueAmount и valuePrice и код обработчика пришлось бы исправить на:
- (void) amount: (int) valueAmount price: (int) valuePrice
{
summa = valueAmount * valuePrice;
}
Чтобы с этим НЕ заморачиваться, многие предпочитают наименование(!) параметров и наименование переменных(!) куда помещаются значения этих параметров называть одним именем.
Таким образом, мысленный переход от "вызываем метод у объекта" к "посылаем сообщение объекту" приводит мозги программиста в порядок. имхо :-)
И нехрен удалять отзывы читателей!!!