Язык является надстройкой над C (любой C код компилируется Objective-C компилятором). Добавлением к Си являются: объектно-ориентированность в стиле Smalltalk (вызов любого метода — посылка сообщения объекту), строки, логический тип (BOOL, значения YES или NO), и др.
Язык отличается от C++ большей гибкостью и количеством метаинформации. При каждом вызове метода Objective C runtime просматривает таблицу виртуальных методов в поисках нужного селектора. Если метод не найден, вызывается универсальный обработчик. У обычных объектов этот обработчик сигнализирует об ошибке (например, выбросом исключения). А у прокси–объектов этот обработчик конструирует удалённый вызов. Сделать прокси в Objective C относительно просто. Метаинформация об объектах содержит сведения о методах и типах аргументов. Достаточно сведений, чтобы прокси объект мог корректно интерпретировать содержимое стека и сериализовать вызов.
На низком уровне вызов метода выглядит как вызов objc_sendmsg(object, selector, arguments). Селектор — это строка, состоящая из идентификаторов, разделённых двоеточиями. Например, если вызов имеет вид:
[mycalendar ordinalityOfUnit:myunit inUnit:myunit2 forDate:mydate]
...то селектор этого вызова "ordinalityOfUnit:inUnit:forDate:". Непосредственно в objc_sendmsg передаётся не строка, а 32битное число. Каждая динамическая библиотека и сама программа при инициализации регистрируют все используемые селекторы, устанавливая соответствие между строками и числами.
arguments — это varargs языка C.
Такой способ вызова позволяет частично бороться с проблемой fragile base class. С одной стороны, API системы подлинно объектно–ориентированное. Например, любая Cocoa программа содержит наследников NSController, который реализован в системной инфраструктуре. С другой стороны, можно относительно легко добавлять новые API к уже существующим классам, являющимися базовыми для пользовательских программ. Именно так Apple и вводит новые API. Пользовательские программы, будь то Camino или Roxio Toast Titanium, не требуют при этом никакой перекомпиляции. Неполнота этого подхода заключается в том, что можно добавлять новые методы, но нельзя добавлять новые поля. Чтобы бороться с этим ограничением, либо с самого начала резервируется достаточно места на будущее, либо создаётся поле типа id, содержащее указатель на внутреннюю реализацию.
По аналогии с интерфейсами в Java, в Objective C есть протоколы. Протокол определяет набор селекторов, которые должен поддерживать объект, реализующий протокол.
В языке определён специальный тип id. id отличается от void* только тем, что компилятор позволяет вызывать методы id, но не позволяет делать это для void*. Во время выполнения любой указатель на объект не отличим от id. Вся разница во время компиляции. Во время компиляции компилятор проверяет поддержку селектора у класса объекта. Например, если переменная имеет тип NSController*, компилятор сделает предупреждение при попытке вызвать неизвестный селектор. Предупреждение сделает, но скомпилировать всё же позволит. Это может быть полезно, если объект являет потомком NSController или вообще не является NSController, что вполне возможно. Поскольку работа со всеми объектами происходит через указатели, а приведение типов для объектов влияет только на восприятие объекта компилятором (никаких runtime проверок), становится возможным использовать утиную типизацию. Используя функции библиотеки Objective C (начинаются на objc_), в принципе, можно выяснить подлинную природу объекта, но компилятор автоматически такие проверки не создаёт.
Для создания объекта в Objective C необходимо вызвать метод класса (похожая схема используется в Ruby). Это делает использование таких паттернов, как абстрактная фабрика или синглтон (одиночка), тривиальными.
Другие особенности:
Для строковых литералов используется запись вида @"строка". Это создаёт строку типа NSString, а не char*, как в C.
Вместо #include есть #import, которая подключает заголовочный файл только один раз.
Несколько изменена схема поиска файла заголовка с учётом каркасов (framework). Каркас — это папка, имеющая расширение .framework. Внутри каркаса могут подпапки (или символические ссылки на них) Headers, Resources, Frameworks. Препроцессор при обработке #import <Cocoa/Cocoa.h> находит файл Cocoa.framework/Headers/Cocoa.h Препроцессор без поддержки каркасов не сможет найти этот файл.
Дата создания: 1986 Создан под влиянием: C Smalltalk Повлиял на: Java Парадигма: объектно-ориентированная Типизация: динамическая, статическая, строгая Принятые расширения файлов: .m Реализации и версии (свернуть все | развернуть все): Apple Objective C Portable Object Compiler gcc Objective C
|