Топ контрибуторов
loading
loading
Знаете ли Вы, что

Свои вопросы для тестов можно добавлять на странице с информацией о тесте. При этом для некоторых тестов добавление вопросов закрыто

Лента обновлений
ссылка Aug 4 12:23
Комментарий от christina132000:
что значит "+2"?
ссылка Aug 3 22:00
Комментарий от dimanaumow:
Только вот никаких конструкторов по умолчанию у типов...
ссылка Aug 3 12:18
Комментарий от GDV29:
Не подскажите, какой можно придумать проект для уровня Jun...
ссылка Aug 2 19:07
Комментарий от dolbatehnik:
(*(f1 + sizeof(f1)/sizeof(f1[0]) - 1))();
Это выраже...
ссылка Aug 1 19:10
Комментарий от Xo4yProytiTest:
*написано в 2009
Статистика

Тестов: 153, вопросов: 8596. Пройдено: 465765 / 2273995.

ООП на Objective-C

head tail Статья
категория
C
дата23.10.2010
авторstosha
голосов13

Тут есть классы и объекты. Объекты конструируются на основе класса. Получают данные, объявленные в классе и часть обработчиков сообщений (методов). Вторая часть методов остается в классе. Сам класс тоже может принимать сообщения. Обычно это сообщения для конструирования новых объектов или вызова каких-то глобальных функций. Это похоже на статические методы в С++. Сам класс не конструируется т.к. своих собственных данных не имеет. Тут нет понятия конструктора (в понимании С++, когда он вызывается автоматически). Есть инициализатор (как в Java). Есть что-то похожее на деструктор. Метод dealloc. Он вызывается по идее автоматически, когда объект перестает существовать. Но вызывается не гарантированно и момент вызова четко не определен (как момент вызова деструктора С++). Поэтому рассчитывать на него особо не следует. Аналогом С++-гого “this” в Obj-C есть “self”. Можно из метода обратиться к вышестоящему в иерархии наследования объекту (родителю) по ключевому слову ”super”.

Все объекты создаются только динамически (выделяется память под данные - члены). Тут нет понятия ссылки на объект. Объект имеет свой указатель. При объявлении любого объекта надо обязательно ставить признак указателя. Символ “*”. Есть исключение. Особый тип “id”. Тут не надо ставить “*”. Фактически она есть, но скрыта. Но дело не в этом. Этим типом можно обозначить любой объект любого класса (видимо С++ идет к тому же). Это очень удобно. Если при объявлении не хочется указывать конкретный класс, то можно просто поставить “id” и все. Или другой пример. Если есть несколько классов, которые наследуют один и тот же протокол (имеют в своем составе метод с совершенно одинаковой сигнатурой), то можно написать функцию, в которую передается объект такого класса с типом id. Тогда внутри этой функции можно смело вызывать общий метод. Такой полиморфизм. Транслятор выводит предупреждения, что такой-то метод возможно не реализован. Если метода нет (класс или объект не обрабатывает сообщение), и нет специального резервного метода на этот случай (forwardInvocation), то возникает ошибка времени выполнения. Приложение зависает. В консоль выводится дамп стека. Поэтому если вы не уверены, обработает объект посланное сообщение, надо предварительно спросить объект, сможет ли он его обработать (respondsToSelector).

Так как объекты создаются только динамически, обязательно надо заботиться об их уничтожении. Для этого тут существует механизм подсчета ссылок. Управлению памяти посвящено не менее 25% любого описания языка, которое я встретил. Есть тут сборщик мусора. Он подключается на уровне проекта (программно не управляется). Не работает на IPhone.

Относительно наследования. Все классы в Obj-С прямо или косвенно наследуются от NSObject. Он является предком всех классов. Наследование реализации только одиночное. Наследуются данные и методы. Методы всегда открыты. В [5] описан способ сокрытия методов. Для этого предлагается использовать категории. При помощи категорий можно добавлять методы в существующие классы. Все остается. Тип объекта остается тем же, как был, но к этому типу можно добавить новые методы. Если объявить категорию в m-файле, а в нем метод, который реализовать в основном классе, то во внешнем интерфейсе (в h-файле) такого метода не будет, а в реализации он будет. Таким образом, пользователь не будет знать о существовании метода. И вообще мы не обязаны объявлять все методы, которые есть в реализации. Используют категории так же в тех случаях, когда класс «чужой», т.е. к исходникам класса нет доступа. Данные можно заключать в приватные, открытые, доступные только наследнику и открытые только внутри модуля. Почти точно как в С++. Множественно наследовать можно только протоколы. Протокол – аналог абстрактного базового класса С++ когда все методы абстрактные. Протокол реализуется через класс, который его наследует. Тут есть тоже ньюансы. Если не хочется реализовывать какой-то метод протокола, можно его объявить в категории и не реализовывать, чтобы транслятор не ругался.

В общем, вся идея классов Obj-С крутится вокруг специальной таблицы, которая имеет грубо говоря имя метода и указатель на обработчик. В режиме выполнения при каждом вызове эта таблица обходится и ищется метод по имени. Система гибкая, но медленная. Хотя пишут, что все сделано, чтобы работало моментально. И не имя хранится, а хеш (селектор) и кеш используют. Эту таблицу можно модифицировать при помощи категорий. Селектор может выступать как отдельный тип. Грубо говоря, селектор-указатель на функцию (метод класса) можно хранить в поле другого класса и вызывать его, минуя операцию посылки сообщения с обходом таблицы и вытекающими расходами ресурсов.

В контейнерах можно хранить только объекты. Это привело к тому, что в массивах нельзя хранить данные базового типа. Например, int. Этот тип обернут в класс. Это хорошо. Ему можно добавлять свои методы. Но объекты такого типа не поддерживают арифметику (перегрузки операций тут нет). Они не поддерживают операций сложения и т.д. А так перед тем, чтоб сложить, их надо привести к соответствующему типу, т.е. послать сообщение объекту.

Для реализации паттерна подписчик (“observer”) тут есть делегаты. Например, есть класс, который в случае наступления какого-то события вызовет ваш объект – делегат. Ваша задача только создать такой объект и передать его классу. Главное, чтобы делегат реализовал тот метод, который будет вызван классом. Удобно сделать делегат категорией NSObject. Тогда класс, который вызывает делегат, будет устроен еще проще. Он может передавать сообщение о наступлении события любому объекту, предварительно запросив у него, сможет ли он обработать это сообщение. Создание категории от NSObject называется созданием «неформального» протокола. То, что вводится директивой @protocol, называют соответственно «формальным» протоколом.

Ссылки:
1. http://ru.wikipedia.org/wiki/Objective-C
2. http://www.onlinefreeebooks.net/go.php?url=http://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/iPhoneAppProgrammingGuide.pdf
3. iOS Reference Library (MSDN) http://developer.apple.com/library/ios/#navigation/
4. http://examples.oreilly.com/9780596809775/ObjC.pdf
5. http://www.williamspublishing.com/Books/978-5-8459-1607-5.html
6. Форум http://classroomm.com/objective-c/
7. Там же [6] вопросы на знание Objective-C (аналогично http://www.quizful.net) от автора книги [5]: http://classroomm.com/objective-c/index.php?board=57.0
8. Архив рассылки по Objective-C: http://lists.apple.com/archives/

Если Вам понравилась статья, проголосуйте за нее

Голосов: 13  loading...
art   bugryn   sava_vodka   pyJIoH   renigat77   BagmutA   ildik   Kamunist   Radium   aizen   salvequick   revo1t   ingwarsmith