Objective-C

редактировать
Универсальный объектно-ориентированный язык программирования

Objective-C
Paradigm Reflective, на основе классов объектно-ориентированное
СемействоC
Разработано Томом Лавом и Брэдом Коксом
Впервые появилось1984; 36 лет назад (1984)
Стабильный выпуск 2.0
Дисциплина набора текста статический, динамический, слабый
OS кросс-платформенный
Имя файла расширения .h,.m,.mm,.M
Веб-сайтdeveloper.apple.com
Основные реализации
Clang, GCC
Под данной
C, Smalltalk
Под местной
Groovy, Java, Nu, Objective-J, Swift

Objective-C - это универсальный, объектно-ориентированный язык программирования, который перв Smalltalk -стиль обмен сообщениями на язык программирования C. Это был основной язык программирования, поддерживаемый Apple для macOS, iOS и их предоставить интерфейсами программирования приложений (API), Cocoa. и Cocoa Touch до появления Swift в 2014 году.

Язык был разработан в начале 1980-х годов. Позже он был выбран в качестве основного языка используемого NeXT для своей операционной системы NeXTSTEP, от которого произошли macOS и iOS. Переносимые программы Objective-C, которые не используют библиотеки Apple или те, которые используют части, которые могут быть перенесены или переопределены для других систем, а также могут быть скомпилированы для любой поддерживаемой коллекции компиляторов GNU (GCC) или Clang.

Программные файлы реализации кода Objective-C обычно имеют расширение.m, в то время как файлы заголовка / интерфейса Objective-C имеют расширения.h, такие же, как C заголовочные файлы. Файлы Objective-C ++ обозначаются расширением.mm.

Содержание

  • 1 История
    • 1.1 Популяризация через NeXT
    • 1.2 Разработка Apple и Swift
  • 2 Синтаксис
    • 2.1 Сообщения
    • 2.2 Интерфейсы и реализация
      • 2.2.1 Интерфейс
      • 2.2.2 Реализация
      • 2.2.3 Создание экземпляра
    • 2.3 Протоколы
    • 2.4 Динамическая типизация
    • 2.5 Пересылка
      • 2.5.1 Пример
      • 2.5.2 Примечания
    • 2.6 Категории
      • 2.6.1 Пример использования категорий
      • 2.6.2 Примечания
    • 2.7 Постановка
    • 2.8 #import
    • 2.9 Компиляция Linux gcc
  • 3 Другие функции
  • 4 Варианты языка
    • 4.1 Цель- C ++
    • 4.2 Objective-C 2.0
      • 4.2.1 Сборка мусора
      • 4.2.2 Свойства
      • 4.2.3 Неустойчивые переменные экземпляры
      • 4.2.4 Быстрое перечисление
      • 4.2.5 Класс extension
      • 4.2.6 Последствия для разработки какао
    • 4.3 Блоки
    • 4.4 Modern Objective-C
      • 4.4.1 Автоматический подсчет ссылок
      • 4.4.2 Литералы
      • 4.4.3 Индексы
    • 4.5 «Современный» синтаксис Objective-C (1997)
    • 4.6 mulle-objc
    • 4.7 Portable O bject Compiler
    • 4.8 GEOS Objective-C
    • 4.9 Clan g
    • 4.10 GNU, GNUstep и WinObjC
  • 5 Использование библиотеки
  • 6 Анализ языка
    • 6.1 Управление памятью
    • 6.2 Философские различия между Objective-C и C ++
  • 7 См. также
  • 8 Ссылки
  • 9 Дополнительная литература
  • 10 Внешние ссылки

История

Objective-C был создан в основном Брэдом Коксом и Томом Лавом в начале 1980- х в их компания Productivity Products International.

В преддверии создания своей компании они познакомились с Smalltalk в Центре технологий программирования ITT Corporation в 1981 году. самая ранняя работа над Objective-C восходит к тому времени. Кокса заинтриговали проблемы истинного повторного использования в разработке программного обеспечения и программировании. Он понял, что такой язык, как Smalltalk, будет неоценимым средством создания сред разработки для разработчиков в ITT. Однако он и Том Лав также признали, что обратная совместимость с C была критически важна для инженерной среды ITT.

Кокс начал писать препроцессор для C, чтобы добавить некоторые возможности Болтовня. Вскоре у него была рабочая реализация объектно-ориентированного расширения для языка C, которое он назвал «OOPC» для объектно-ориентированного прекомпилятора. В 1982 году Лав был нанят компанией Schlumberger Research и получил возможность приобрести первую коммерческую копию Smalltalk-80, которая в дальнейшем повлияла на развитие их детища. Чтобы показать реальный прогресс, Кокс показал, что создание взаимозаменяемых программных компонентов действительно требует лишь нескольких практических изменений инструментов. В частности, они должны обеспечивать гибкую поддержку объектов, поставляться с полезным набором библиотек и позволять объединять код (и любые ресурсы, необходимые для кода) в один кроссплатформенный формат.

Лав и Кокс в конечном итоге создали PPI для коммерциализации своего продукта, который объединил компилятор Objective-C с библиотеками классов. В 1986 году Кокс опубликовал основное описание Objective-C в его первоначальной форме в книге «Объектно-ориентированное программирование, эволюционный подход». Он был осторожен, чтобы указать, что проблема повторного использования - это нечто большее, чем просто то, что использует Objective-C, язык часто обнаруживает, сравнивает функции с другими языками.

Популяризация через NeXT

В 1988 году NeXT лицензировала Objective-C у StepStone (новое название PPI, владелец торговой марки Objective-C) и расширила GCC компилятор для поддержки Objective-C. NeXT разработала библиотеки AppKit и Foundation Kit, на которых были основаны пользовательский интерфейс NeXTSTEP и Interface Builder. Хотя рабочие станции NeXT не имеют большого влияния на рынок, инструменты получили широкое признание в отрасли. Это к тому же, что NeXT отказалась от производства оборудования и сосредоточилась на программных инструментов, продав NeXTSTEP (и OpenStep) в качестве платформы для индивидуального программирования.

Чтобы обойти условия GPL, NeXT изначально намеревалась поставлять интерфейс Objective-C отдельно, позволяя пользователю связать его с GCC для создания исполняемого файла компилятора. Первоначально принятый Ричардом М. Столлманом, этот план был отклонен после того, как Столлман проконсультировался с юристами GNU и NeXT согласился сделать Objective-C частью GCC.

Работа по расширению GCC стратегл Нарофф, который присоединился к NeXT из StepStone. Изменения компилятора были сделаны доступными в соответствии с условиями лицензии GPL, но библиотеки времени выполнения - нет, что сделало вклад с открытым исходным кодом непригодным для широкой публики. Это привело к тому, что другие стороны разработали такие библиотеки времени выполнения лицензией с открытым исходным кодом. Позже Стив Нарофф также был основным участником работы в Apple над созданием интерфейса Objective-C для Clang.

. Проект GNU начал работу над своей свободной программной реализацией Какао <335.>, названный GNUstep, на основе стандарта OpenStep. Деннис Глаттинг написал первую среду выполнения GNU Objective-C в 1992 году. Среда выполнения GNU Objective-C, которая используется с 1993 года, была ограничена Крестеном Крабом Торупом, когда он был студентом университета в Дания. Торуп также работал в NeXT с 1993 по 1996 год.

Разработка Apple и Swift

После приобретения NeXT в 1996 году Apple Computer использовал OpenStep в своей тогда новой операционной системе, Mac OS X. Это включало Objective-C, инструмент разработчика NeXT на основе Objective-C, Project Builder и его инструмент дизайна, Interface Builder, оба теперь объединены в одно приложение, Xcode. Большая часть текущего Какао API от Apple использует основу объектах интерфейса OpenStep и является наиболее средой Objective-C, используемой для активной разработки.

На WWDC 2014 Apple представила новый язык, Swift, который характеризовался как «Objective-C без C».

Синтаксис

Objective-C представляет собой тонкий слой поверх C и является «строгим надмножеством » языка C, что означает, что можно компилировать любую программу C с помощью компилятора Objective-C и свободный вход код языка C в класс Objective-C.

Objective-C выводит свой объектный синтаксис из Smalltalk. Весь синтаксис для не объектно-ориентированных операций (включая примитивные переменные, предварительную обработку, выражение, объявления функций и вызовы функций) идентичен синтаксису C, в то время как синтаксис объектно-ориентированных функций реализацией Smalltalk-стиля обмена сообщениями.

Сообщения

Модель объектно-ориентированного программирования Objective-C основана на передаче сообщений экземпляров объектов. В Objective-C метод не вызывается; один отправляет сообщение. Это отличается от модели программирования в стиле Simula, используемой в C ++. Разница между этими двумя концепциями заключается в том, как выполняется код, на котором указан этот метод или сообщения. В языке в стиле Simula имя метода в большинстве случаев привязано к части кода в целевом классе компилятором. В Smalltalk и Objective-C цель решается во время выполнения, при этом принимающий объект сам интерпретирует сообщение. Метод идентифицируется селектором или SEL - уникальным представителем для каждого имени сообщения, часто просто строкой с завершающим NUL, представляющий его имя - и разрешается в методе C указатель, реализующий его: IMP. Следующим является то, что в системе передачи сообщений нет проверки типов. Объект, которому направлено сообщение - получатель - не гарантирует ответа на сообщение, и если это не так, возникает исключение.

Отправка сообщений объект, на который указывает по указателю объект, следующий код в методе C ++ :

obj ->(аргумент);

В Objective-C это записывается следующим образом:

[метод объекта: аргумент];

Вызов "метода" транслируется компилятором в семейство функций времени выполнения objc_msgSend (id self, SEL op,...). Различные реализации обрабатывают современные дополнения, такие как super. В семействах GNU эта функция называется objc_msg_sendv, но она устарела в пользу современной системы поиска под objc_msg_lookup.

Оба стиля программирования имеют свои сильные и слабые стороны. Объектно-ориентированное программирование в стиле Simula (C ++ ) допускает множественное наследование и более быстрое выполнение за счет использования привязки времени компиляции, когда это возможно, но оно не поддерживает динамическая привязка по умолчанию. Это также заставляет все методы работать, если они не являются абстрактными. Программирование в стиле Smalltalk, используемое в Objective-C, позволяет сообщениям оставаться нереализованными, а метод разрешается для его реализации во время выполнения. Например, сообщение может быть отправлено набору объектов, на которое отвечает только от некоторых, не опасаясь возникновения ошибок времени выполнения. Передача сообщений также не требует, чтобы объект был определен во время компиляции. Для вызова метода в производном объекте по-прежнему требуется реализация. (См. динамическая типизация ниже, чтобы узнать больше о преимуществах динамического (позднего) связывания.)

Интерфейсы и реализация

Objective-C требует, чтобы интерфейс и реализация класс находиться в отдельно объявленных блоках кода. По соглашению разработчики загружают интерфейс в файл заголовка , а используют - в файл кода. Файлы заголовков, обычно с суффиксом.h, похожи на файлы заголовков C, могут быть очень похожи на файлы реализации (методов), обычно с суффиксом.m, могут быть очень похожи на файлы кода C.

Интерфейс

Аналогично объявлениям классов, используемых в других объектно-ориентированных языках, таких как C ++ или Python.

Интерфейс класса обычно определяется в файле заголовка. Распространенным соглашением является обозначение файла заголовка после имени класса, например Ball.h будет содержать интерфейс для класса Ball.

Объявление интерфейса принимает форму:

@interface classname: superclassname {// переменныерара} + classMethod1; + (return_type) classMethod2; + (return_type) classMethod3: (param1_type) param1_varName; - (return_type) instanceMethod1With1Parameter: (param1_type) param1_varName; - (return_type) instanceMethod2With2Parameters: (param1_type) param1_varName param2_callName: (param2_type) param2_varName; @end

В приведенном выше описании знаки плюса обозначают класса или методы, которые можно вызвать в самом классе (не в экземплярах), а знаки минус обозначают методы экземпляра, который может быть вызван только в конкретном экземпляре класса. Методы класса также не имеют доступа к переменным экземплярам.

Приведенный выше код примерно эквивалентен следующему интерфейс C ++ :

class classname: public superclassname {protected: // instance variables public: // Class (static) functions static void * classMethod1 (); статический return_type classMethod2 (); статический return_type classMethod3 (param1_type param1_varName); // Экземпляр (член) функции return_type instanceMethod1With1Parameter (param1_type param1_varName); return_type instanceMethod2With2Parameters (param1_type param1_varName, param2_type param2_varName = default); };

Обратите внимание, что instanceMethod2With2Parameters: param2_callName: демонстрирует чередование сегментов селектора с выражениями аргументов, для которых нет прямого эквивалента в C / C ++.

Возвращаемые типы могут быть любым стандартным типом C, указателем на общий объект Objective-C, указателем на объект определенного типа, например NSArray *, NSImage * или NSString *. или указатель на класс, к которому принадлежит метод (тип экземпляра). Тип возврата по умолчанию - это универсальный тип Objective-C id.

Аргументы вызываемого аргумента начинаются с имени, обозначающего аргумента, являющегося известным методом, за которым следует двоеточие, за которым следует тип средства в круглых скобках и имя аргумента. Этикетку можно не указывать.

- (void) setRangeStart: (int) начало конец: (int) конец; - (void) importDocumentWithName: (NSString *) имя withSpecifiedPreferences: (Preferences *) prefs beforePage: (int) insertPage;

Производным от определения является категория, которая позволяет методы к существующим классам.

Реализация

Интерфейс объявляет только интерфейс класса, а не сами методы: фактический код написан в файле реализации. Файлы реализации (методы) обычно имеют расширение .m, которое изначально означало «сообщения».

@implementation classname + (return_type) classMethod {// реализация} - (return_type) instanceMethod {// реализация} @end

Методы написаны с использованием объявлений их интерфейса. Сравнение Objective-C и C:

- (int) метод: (int) i {return [self square_root: i]; }
функция int (int i) {return square_root (i); }

Синтаксис допускает псевдо- именование аргументов.

- (void) changeColorToRed: (float) red green: (float) green blue: (float) blue {//... Реализация...} / / Вызывается так: [myColor changeColorToRed: 5.0 зеленый: 2.0 синий: 6.0];

Внутреннее описание метода различается в зависимости от реализации Objective-C. Если myColor относится к классу Color, метод экземпляра -changeColorToRed: green: blue: может иметь внутреннюю метку _i_Color_changeColorToRed_green_blue. i предназначена для ссылок на методы экземпляра с добавлением имен класса, а затем методами и заменой двоеточий навания. Его нельзя изменить в соответствии со стилем кодирования или выражением, как с истинно именованными функциями.

внутренние имена функции редко используются напрямую. Как правило, сообщения преобразуются в вызовы функций, в библиотеке времени выполнения Objective-C. Во время связывания не обязательно известно, какой метод будет вызван, потому что класс получателя (объект, отправляющий сообщение) не обязательно должен быть указан до времени выполнения.

Создание экземпляра

После того, как класс Objective-C написан, он может быть создан. Для этого сначала выделяется неинициализированный экземпляр класса (объекта), а затем инициализируется его. Объект не является полностью функциональным, пока не будут выполнены оба шага. Эти шаги должны быть выполнены с помощью одной строки кода, чтобы никогда не существовало выделенного объекта, который не прошел инициализацию (и потому что неразумно это промежуточный результат, поскольку -initможет возвращать другой объект, чем тот, на котором он называется).

Создание экземпляра с инициализатором по умолчанию без параметров:

MyObject * foo = [[MyObject alloc] init];

Создание экземпляра с настраиваемым инициализатором:

MyObject * foo = [[MyObject alloc] initWithString: myString];

В случае, если пользовательская инициализация не выполняется, вместо сообщений alloc-init можно использовать «новый» метод:

MyObject * foo = [MyObject new];

Кроме того, некоторые классы реализуют инициализаторы методов класса. Как и + new, они объединяют + allocи -init, но в отличие от + new, они возвращают автоматически выпущенный экземпляр. Некоторые инициализаторы принимают параметры класса:

MyObject * foo = [MyObject object]; MyObject * bar = [MyObject objectWithString: @ "Википедия :)"];

Сообщение выделяет достаточно памяти для хранения всех экземпляра объекта, устанавливает все переменные экземпляры в нулевые значения и превращает память в экземпляр класса; ни в какой момент во время инициализации памяти не является экземпляром суперкласса.

Сообщение инициализации реализации настройки экземпляра после создания. Метод инициализации часто записывается следующим образом:

- (id) init {self = [super init]; if (self) {// здесь выполняем инициализацию объекта} return self; }

В приведенном выше примере обратите внимание на возвращаемый тип id. Этот тип означает «указатель на любой объект» в Objective-C (см. Раздел Динамическая типизация).

Шаблон инициализатора используется, чтобы гарантировать, что объект правильно инициализирован его суперклассом до того, как метод init выполнит свою инициализацию. Он выполняет следующие действия:

  1. self = [super init]
    Посылает экземпляру суперкласса сообщение инициализации и присваивает результат self (указатель на текущий объект).
  2. if (self)
    Проверяет, действителен ли возвращаемый указатель объекта перед выполнением любой инициализации.
  3. return self
    Возвращает значение self вызывающей стороне.

Недействительный указатель объекта имеет значение ноль; условные операторы, такие как «if», обрабатывают nil как нулевой указатель, поэтому код инициализации не будет выполняться, если [super init] вернул nil. Если есть ошибка при инициализации, метод init должен выполнить любую необходимую очистку, включая отправку сообщения «release» самому себе, и вернуть nil, чтобы указать, что инициализация не удалась. Любая проверка на наличие таких ошибок должна выполняться только после вызова инициализации суперкласса, чтобы гарантировать, что уничтожение объекта будет выполнено правильно.

Если класс имеет более одного метода инициализации, только один из них («назначенный инициализатор») должен следовать этому шаблону; другие должны вызывать назначенный инициализатор вместо инициализатора суперкласса.

Протоколы

В других языках программирования они называются «интерфейсами».

Objective-C был расширен в NeXT, чтобы представить концепцию множественного наследования спецификации, но не реализации, посредством введения протоколов. Это шаблон, достижимый либо как абстрактный множественный наследуемый базовый класс в C ++, либо как «интерфейс» (как в Java и C # ). Objective-C использует специальные протоколы, называемые неформальными протоколами, и протоколы, поддерживаемые компилятором, называемые формальными протоколами.

Неформальный протокол - это список методов, которые класс может реализовать. Это указано в документации, так как в языке его нет. Неофициальные протоколы реализованы как category (см. Ниже) в NSObject и часто включают дополнительные методы, которые, если они реализованы, могут изменить поведение класса. Например, класс текстового поля может иметь делегата , который реализует неформальный протокол с дополнительным методом для выполнения автозаполнения текста, введенного пользователем. Текстовое поле определяет, реализует ли делегат этот метод (через Reflection ), и, если да, вызывает метод делегата для поддержки функции автозаполнения.

Формальный протокол аналогичен интерфейсу в Java, C # и Ada 2005. Это список методов, которые любой класс может объявить для реализации. Версии Objective-C до 2.0 требовали, чтобы класс реализовал все методы в протоколе, который он объявляет как принимающий; компилятор выдаст ошибку, если класс не реализует все методы из своих объявленных протоколов. В Objective-C 2.0 добавлена ​​поддержка пометки определенных методов в протоколе как необязательных, и компилятор не будет требовать реализации дополнительных методов.

Должен быть объявлен класс для реализации этого протокола, чтобы говорилось, что он соответствует ему. Это можно обнаружить во время выполнения. Формальные протоколы не могут предоставить никаких реализаций; они просто гарантируют вызывающим абонентам, что классы, соответствующие протоколу, предоставят реализации. В библиотеке NeXT / Apple протоколы часто используются системой распределенных объектов для представления возможностей объекта, выполняемого в удаленной системе.

Синтаксис

@protocol NSLocking - (void) lock; - (недействительная) разблокировка; @end

означает, что существует абстрактная идея блокировки. Заявив в определении класса, что протокол реализован,

@interface NSLock: NSObject //... @end

экземпляры NSLock заявляют, что они предоставят реализацию для двух методов экземпляра.

Динамическая типизация

Objective-C, как и Smalltalk, может использовать динамическую типизацию : объекту может быть отправлено сообщение, которое не указано в его интерфейсе. Это может обеспечить повышенную гибкость, так как позволяет объекту «захватить» сообщение и отправить сообщение другому объекту, который может ответить на сообщение соответствующим образом, или аналогичным образом отправить сообщение другому объекту. Такое поведение известно как пересылка сообщений или делегирование (см. Ниже). В качестве альтернативы можно использовать обработчик ошибок, если сообщение не может быть отправлено. Если объект не пересылает сообщение, не отвечает на него или не обрабатывает ошибку, система генерирует исключение времени выполнения. Если сообщения отправляются в nil (указатель на нулевой объект), они будут игнорироваться или вызывать общее исключение, в зависимости от параметров компилятора.

Информация о статической типизации также может быть добавлена ​​к переменным. Затем эта информация проверяется во время компиляции. В следующих четырех утверждениях предоставляется все более конкретная информация о типах. Операторы эквивалентны во время выполнения, но дополнительная информация позволяет компилятору предупреждать программиста, если переданный аргумент не соответствует указанному типу.

- (недействительно) setMyValue: (id) foo;

В приведенном выше утверждении foo может относиться к любому классу.

- (void) setMyValue: (id ) foo;

В приведенном выше утверждении foo может быть экземпляром любого класса, который соответствует протоколу NSCopying.

- (пусто) setMyValue: (NSNumber *) foo;

В приведенном выше утверждении foo должен быть экземпляром класса NSNumber.

- (void) setMyValue: (NSNumber *) foo;

В приведенном выше утверждении foo должен быть экземпляром класса NSNumber и соответствовать протоколу NSCopying.

В Objective-C все объекты представлены как указатели, и статическая инициализация не разрешена. Самый простой объект - это тип, на который указывает id (objc_obj *), у которого есть только указатель isa, описывающий его класс. Другие типы из C, такие как значения и структуры, не изменились, потому что они не являются частью объектной системы. Это решение отличается от объектной модели C ++, в которой объединены структуры и классы.

Пересылка

Objective-C разрешает отправку сообщения объекту, который может не отвечать. Вместо того, чтобы отвечать или просто отбрасывать сообщение, объект может переслать сообщение объекту, который может ответить. Пересылка может использоваться для упрощения реализации определенных шаблонов проектирования , таких как шаблон наблюдателя или шаблон прокси.

. Среда выполнения Objective-C определяет пару методов в Объект

  • методы пересылки:
    - (retval_t) forward: (SEL) sel args: (arglist_t) args; // с GCC - (id) forward: (SEL) sel args: (marg_list) args; // с системами NeXT / Apple
  • методы действий:
    - (retval_t) performv: (SEL) sel args: (arglist_t) args; // с GCC - (id) performv: (SEL) sel args: (marg_list) args; // с системами NeXT / Apple

Объекту, желающему реализовать переадресацию, нужно только переопределить метод пересылки новым методом для определения поведения пересылки. Метод действия performv :: не нужно переопределять, поскольку этот метод просто выполняет действие на основе селектора и аргументов. Обратите внимание на тип SEL, который является типом сообщений в Objective-C.

Примечание: в OpenStep, Cocoa и GNUstep, обычно используемых фреймворках Objective-C, не используется класс Object. Метод - (void) forwardInvocation: (NSInvocation *) anInvocation класса NSObject используется для пересылки.

Пример

Вот пример программы, демонстрирующей основы пересылки.

Forwarder.h
#import @interface Forwarder: объект {идентификатор получателя; // Объект, которому мы хотим переслать сообщение. } // Методы доступа. - (id) получатель; - (id) setRecipient: (id) _recipient; @end
Forwarder.m
#import "Forwarder.h" @implementation Forwarder - (retval_t) forward: (SEL) sel args: (arglist_t) args {/ * * Проверить, действительно ли получатель отвечает на сообщение. * Это может быть или нежелательно, например, если получатель * в свою очередь не отвечает на сообщение, он может выполнить пересылку * самостоятельно. * / if ([получатель responseToSelector: sel]) {return [получатель performv: sel args: args]; } else {return [собственная ошибка: «Получатель не отвечает»]; }} - (id) setRecipient: (id) _recipient {[автозапуск получателя]; получатель = [_recipient удержать]; вернуть себя; } - (id) получатель {получатель возврата; } @end
Recipient.h
#import // Простой объект Recipient. @interface Получатель: Объект - (id) привет; @end
Recipient.m
#import "Recipient.h" @implementation Recipient - (id) hello {printf ("Получатель передает привет! \ n"); вернуть себя; } @end
main.m
#import "Forwarder.h" #import "Recipient.h" int main (void) {Forwarder * forwarder = [Forwarder new]; Получатель * получатель = [Получатель новый]; [отправитель setRecipient: получатель]; // Устанавливаем получателя. / * * Сервер пересылки наблюдений не отвечает на приветственное сообщение! Он будет * переадресован. Все нераспознанные методы будут перенаправлены * получателю * (если получатель ответит им, как написано в Forwarder) * / [forwarder hello]; [выпуск получателя]; [разрешение экспедитора]; возврат 0; }

Примечания

При компиляции с использованием gcc компилятор сообщает:

$ gcc -x objective-c -Wno-import Forwarder.m Recipient.m main.m -lobjc main.m: В функции `main ': main.m: 12: предупреждение:` Forwarder' не отвечает на `hello '$

Компилятор сообщает ранее сделанную мысль, что Сервер пересылки не отвечает на приветственные сообщения. В этом случае можно безопасно игнорировать предупреждение, так как пересылка была реализована. Запуск программы дает следующий результат:

$./a.out Получатель передает привет!

Категории

При разработке Objective-C одной из основных проблем была возможность сопровождения больших баз кода. Опыт из мира структурированного программирования показал, что одним из основных способов улучшения кода было разбиение его на более мелкие части. Objective-C заимствовал и расширил концепцию категорий из реализаций Smalltalk, чтобы помочь в этом процессе.

Кроме того, методы внутри категории добавляются к классу во время времени выполнения. Таким образом, категории позволяют программисту добавлять методы в существующий класс - открытый класс - без необходимости перекомпилировать этот класс или даже иметь доступ к его исходному коду. Например, если система не содержит средства проверки орфографии в своей реализации String, его можно добавить без изменения исходного кода String.

Методы внутри категорий становятся неотличимы от методов в классе при запуске программы. Категория имеет полный доступ ко всем переменным экземпляра в классе, включая частные переменные.

Если категория объявляет метод с той же сигнатурой метода, что и существующий метод в классе, метод категории принимается. Таким образом, категории могут не только добавлять методы в класс, но и заменять существующие методы. Эту возможность можно использовать для исправления ошибок в других классах путем переписывания их методов или для глобального изменения поведения класса в программе. Если две категории имеют методы с одинаковыми именами, но разными сигнатурами, не определено, какой метод категории будет принят.

Другие языки пытались добавить эту функцию разными способами. сделал еще один шаг в системе Objective-C и позволил также добавлять переменные. В других языках вместо этого использовались решения на основе прототипов, наиболее примечательным из которых является Self.

. Языки C # и Visual Basic.NET реализуют внешне похожие функции в форме методов расширения, но у них отсутствует доступ к закрытым переменным класса. Ruby и несколько других языков динамического программирования называют эту технику «исправлением обезьяны ».

Logtalk реализует концепцию категорий (как первоклассных сущностей), которая включает в себя функциональность категорий Objective-C (категории Logtalk также могут использоваться в качестве детализированных единиц композиции при определении, например, новых классов или прототипов; в частности, категорию Logtalk можно виртуально импортировать любым количеством классов и прототипов).

Пример использования категорий

В этом примере создается целочисленный класс, определяя сначала базовый класс с реализованными только методами доступа и добавляя две категории, Арифметика и Дисплей, расширяющие базовый класс. Хотя категории могут получать доступ к частным членам данных базового класса, часто рекомендуется обращаться к этим частным элементам данных с помощью методов доступа, что помогает сохранять категории более независимыми от базового класса. Реализация таких средств доступа - типичное использование категорий. Другой - использовать категории для добавления методов к базовому классу. Однако использование категорий для переопределения подклассов, также известного как исправление обезьян, не считается хорошей практикой. Informal protocols are implemented as a category on the base NSObject class. By convention, files containing categories that extend base classes will take the name BaseClass+ExtensionClass.h.

Integer.h
#import @interface Integer : Object { int integer; } - (int)integer; - (id)integer:(int)_integer; @end
Integer.m
#import "Integer.h" @implementation Integer - (int) integer { return integer; } - (id) integer: (int) _integer { integer = _integer; вернуть себя; } @end
Integer+Arithmetic.h
#import "Integer.h" @interface Integer (Arithmetic) - (id) add: (Integer *) addend; - (id) sub: (Integer *) subtrahend; @end
Integer+Arithmetic.m
# import "Integer+Arithmetic.h" @implementation Integer (Arithmetic) - (id) add: (Integer *) addend { return [self integer: [self integer] + [addend integer]]; } - (id) sub: (Integer *) subtrahend { return [self integer: [self integer] - [subtrahend integer]]; } @end
Integer+Display.h
#import "Integer.h" @interface Integer (Display) - (id) showstars; - (id) showint; @end
Integer+Display.m
# import "Integer+Display.h" @implementation Integer (Display) - (id) showstars { int i, x = [self integer]; for (i = 0; i < x; i++) { printf("*"); } printf("\n"); return self; } - (id) showint { printf("%d\n", [self integer]); return self; } @end
main.m
#import "Integer.h" #import "Integer+Arithmetic.h" #import "Integer+Display.h" int main(void) { Integer *num1 = [Integer new], *num2 = [Integer new]; int x; printf("Enter an integer: "); scanf("%d", x); [num1 integer:x]; [num1 showstars]; printf("Enter an integer: "); scanf("%d", x); [num2 integer:x]; [num2 showstars]; [num1 add:num2]; [num1 showint]; return 0; }

Notes

Compilation is performed, for example, by:

gcc -x objective-c main.m Integer.m Integer+Arithmetic.m Integer+Display.m -lobjc

One can experiment by leaving out the #import "Integer+Arithmetic.h" and [num1 add:num2] lines and omitting Integer+Arithmetic.m in compilation. The program will still run. This means that it is possible to mix-and-match added categories if needed; if a category does not need to have some ability, it can simply not be compile in.

Posing

Objective-C permits a class to wholly replace another class within a программа. The replacing class is said to "pose as" the target class.

Cl задница позирования была объявлена ​​устаревшей в Mac OS X v10.5 и недоступна в 64-битной среде выполнения. Подобная функциональность может быть достигнута с помощью переключения методов в категориях, при котором реализация одного метода заменяется другой, имеющей ту же сигнатуру.

Для версий, все еще поддерживающих позирование, все сообщения, отправленные в целевой класс, вместо этого принимаются классом позирования. Есть несколько ограничений:

  • Класс может представлять собой только один из своих прямых или косвенных суперклассов.
  • Позирующий класс не должен определять никаких новых переменных экземпляра, которые отсутствуют в целевом классе (хотя он может определять или методы переопределения).
  • Целевой класс, возможно, не получил никаких сообщений до позирования.

Представление, как и категории, позволяет глобальное расширение существующих классов. Позирование разрешает две функции, отсутствующие в категориях:

  • Позирующий класс может вызывать переопределенные методы через super, таким образом, включая реализацию целевого класса.
  • Позирующий класс может переопределить методы, определенные в категориях.

Для например,

@interface CustomNSApplication: NSApplication @end @implementation CustomNSApplication - (void) setMainMenu: (NSMenu *) menu {// сделать что-то с меню} @end class_poseAs ([CustomNSApplication class], [NSApplication class]);

Это перехватывает каждый вызов setMainMenu для NSApplication.

#import

В языке C директива предварительной компиляции #includeвсегда вызывает вставку содержимого файла в исходный код в этой точке. Objective-C имеет эквивалентную директиву #import, за исключением того, что каждый файл включается только один раз для каждой единицы компиляции, что устраняет необходимость в include guards.

компиляция Linux gcc

// ФАЙЛ: черт возьми #import int main (int argc, const char * argv) {/ * моя первая программа на Objective-C * / NSLog (@ "Hello, World! \ n"); возврат 0; }
# Компиляция системы для компилятора gcc и MinGW: $ gcc \ $ (gnustep-config --objc-flags) \ -o hello \ hello.m \ -L / GNUstep / System / Library / Libraries \ -lobjc \ -lgnustep-base $./hello

Другие функции

Возможности Objective-C часто позволяют находить гибкие и часто простые решения проблем программирования.

  • Делегирование методов другими объектам и удаленный вызов могут быть легко реализованы с использованием системы и пересылки сообщений.
  • Swizzling указателя isaпозволяет классам изменяться в время выполнения. Обычно используется для отладки, когда созданные единственные объекты превращаются в зомби-объекты, цель - сообщить об ошибке, когда кто-то их вызывает. Swizzling также использовался в Enterprise Objects Framework для создания ошибок базы данных. Swizzling используется сегодня Apple Foundation Framework для реализации.

Варианты языка

Objective-C ++

Objective-C ++ - это вариант языка, принятый интерфейс для GNU Коллекция компиляторов и Clang, которые могут компилировать исходные файлы, используя комбинацию синтаксиса C ++ и Objective-C. Objective-C ++ превосходит к C ++ расширения, которые используются для унификации семантики, положенного в основе различных языковых функций, ограничения:

  • Класс C ++ не может быть производным от класса Objective-C и наоборот.
  • Пространства имен C ++ не могут быть объявлены внутри объявления Objective-C.
  • Объявления Objective-C могут появляться только в глобальной области, а не внутри пространства имен C ++
  • Классы Objective-C не могут иметь переменные экземпляры классов C ++, в отсутствует конструктор по По умолчанию которые имеют один или несколько виртуальных методов, но указатели на объекты C ++ они включают в число экземпляра без ограничений (выделяйте их с помощью нового в методе -init).
  • Семантика C ++ "по значению" не может работать к объекту Objective-C, которые доступны только через указатели.
  • Объявление Objective-C не может находиться внутри объявления шаблона C ++ и наоборот. Однако типы Objective-C (например, Classname *) могут выбрать один из вариантов шаблона C ++.
  • Обработка исключений Objective-C и C ++ отличается; обработчики каждого из них не могут обрабатывать исключение другого типа. В результате деструкторы объекта не запускаются. Это смягчается в недавних средах выполнения "Objective-C 2.0", поскольку исключение Objective-C либо полностью заменяется исключениями C ++ (среда выполнения Apple), либо частично, когда библиотека Objective-C ++ связана (GNUstep libobjc2).
  • Objective -C блоки и C ++ 11 лямбды имеют разные сущности. Однако при передаче лямбда-выражения там, где предлагается блок, в macOS создается прозрачный блок.

Objective-C 2.0

На Всемирной конференции разработчиков 2006 г. Apple объявила о выпуске «Objective-C 2.0», версия языка Objective-C, включающая «современную сборку мусора, улучшение синтаксиса, улучшение производительности во время выполнения и поддержку 64-разрядных систем». Mac OS X v10.5, выпущенная в октябре 2007 г., включающая компилятор Objective-C 2.0. GCC 4.6 поддерживает множество новых функций Objective-C, таких как объявленные и синтезированные свойства, точечный синтаксис, быстрое перечисление, дополнительные протоколы, атрибуты метода / протокола / класса, расширения классов и новый API среды выполнения GNU Objective-C.

Обозначение Objective-C 2.0 представляет собой прорыв в системе управления версией языка, последней версией Objective-C для NeXT была "objc4". Это имя проекта было сохранено в последнем выпуске устаревшего исходного кода среды выполнения Objective-C в Mac OS X Leopard (10.5).

Сборка мусора

Objective-C 2.0 предоставил необязательный консервативный сборщик мусора для поколений. При запуске в режиме обратной совместимости среда сохранения превратила операции подсчета ссылок, такие как «освободить» и «освободить», в no-ops. Когда сборка мусора была включена, все объекты подлежали сборке мусора. Обычные указатели C могут быть квалифицированы с помощью "__strong", чтобы также инициировать перехват базового компилятора барьера записи и, таким образом, участвовать в сборке мусора. Также была предоставлена ​​слабая подсистема обнуления, такие, что указатели, помеченные как «__weak», устанавливаются в ноль при сборе объекта (или, проще говоря, GC). Сборщик мусора не существует в реализации Objective-C 2.0 для iOS. Сборка мусора в Objective-C выполняется в фоновом потоке с помощью приоритетом и может быть останавливаться при пользовательских событиях, чтобы обеспечить взаимодействие с пользовательскими событиями.

Сборка мусора устарела в Mac OS X v10.8 с использованием Автоматический подсчет ссылок (ARC). Objective-C на iOS 7 на ARM64 19 использует битов из 64-битного слова для хранения счетчика ссылок в виде тегированных указателей.

Свойства

Objective -C 2.0 вводит новый синтаксис для объявления число экземпляров как свойства с дополнительными атрибутами для настройки генерации методов доступа. Свойства в некотором смысле являются общедоступными переменными экземплярами; то есть объявление объявления экземпляра как свойства классам доступ (возможно, ограниченный, например, только для чтения) к этомуству. Свойство может быть объявлено как «только для чтения» и может быть обеспечено семантикой хранения, таким как назначить, копиюили оставить. По умолчанию рассматриваются свойства атомарными, что приводит к блокировке, препятствует одновременному доступу к ним нескольких потоков. Свойство может быть объявлено как неатомарное, что снимает эту блокировку.

@interface Person: NSObject {@public NSString * name; @private int age; } @property (копия) NSString * name; @property (только для чтения) int age; - (id) initWithAge: (int) возраст; @end

Свойства реализуются посредством ключевого слова @synthesize, которое генерирует методы получения (и установки, если не только для чтения) в соответствии с объявлением свойств. В качестве альтернативных методов используются другие методы, используемые явно, или можно использовать использование @dynamic, чтобы указать, что методы доступа будут использоваться другими средствами. При компиляции с использованием clang 3.1 или выше все свойства, которые явно не объявлены с помощью @dynamic, помечены только для чтенияили имеют полные реализованные средства получения и установки, будут автоматически неявно неявно @ синтезировать'd.

@implementation Person @synthesize имя; - (id) initWithAge: (int) initAge {self = [super init]; if (self) {// ПРИМЕЧАНИЕ: прямое присвоение альтернативных экземпляров, а не средство установки свойств age = initAge; } return self; } - (int) age {возраст возврата; } @end

К свойствам можно получить доступ, используя точечную нотацию или кодирование значений ключа, по имени с помощью методов "valueForKey:" / "setValue: forKey:".

Человек * aPerson = [[Распределение лиц] initWithAge: 53]; aPerson.name = @ "Стив"; // ПРИМЕЧАНИЕ: точечная нотация, используемый синтезированный установщик, // эквивалент [aPerson setName: @ "Steve"]; NSLog (@ "Доступ по сообщению (% @), точечная нотация (% @), имя свойства (% @) и прямой доступ к используемым экземплярам (% @)", [имя лица], имя лица, [лица лицаForKey: @ "имя"], Лицо ->имя);

Чтобы использовать точечную нотацию для вызова средств доступа к свойствам в методе экземпляров, следует использовать слово "self":

- (недействительно) IntroductionMyselfWithProperties: (BOOL) useGetter {NSLog (@ "Привет, меня зовут% @. ", (useGetter? self.name: name)); // ПРИМЕЧАНИЕ: доступ к геттеру и ivar}

Свойства класса или протокола могут быть динамически интроспектированы.

int i; int propertyCount = 0; objc_property_t * propertyList = class_copyPropertyList ([aPerson class], propertyCount); for (i = 0; i < propertyCount; i++) { objc_property_t *thisProperty = propertyList + i; const char *propertyName = property_getName(*thisProperty); NSLog(@"Person has a property: '%s'", propertyName); }

Неустойчивые переменные экземпляры

Objective-C 2.0 обеспечивает нехрупкие переменные экземпляры, если они поддерживаются средой выполнения (т. е. при создании кода для 64-битной macOS и всех iOS В) Эта функция позволяет внести два важных улучшения в код Objective-C:

  • Она устраняет проблема хрупкого двоичного интерфейса ; суперклассы могут размеры, не влияя на двоичную совместимость.
  • Это позволяет переменным экземплярам, ​​обеспечивающим поддержку свойств, синтезироваться во исполнение без их объявления в интерфейсе класса.

Быстрое перечисление

Вместо использования объекта NSEnumerator или индексов для итерации по коллекции Objective-C 2.0 предлагает синтаксис быстрого перечисления. В Objective-C 2.0 следующие ци клы функционально эквивалентны, но имеют разные характеристики.

// Использование NSEnumerator NSEnumerator * enumerator = [thePeople objectEnumerator]; Человек * p; while ((p = [перечислитель nextObject])! = nil) {NSLog (@ "% @ is% i лет.", [p name], [p age]); }
// Использование индексов для (int i = 0; i < [thePeople count]; i++) { Person *p = [thePeople objectAtIndex:i]; NSLog(@"%@ is %i years old.", [p name], [p age]); }
// Использование быстрого перечисления для (Person * p in thePeople) {NSLog (@ "% @ is% i years old.", [P name ], [p age]);}

Быстрое перечисление генерирует более эффективный код, чем стандартное перечисление, потому что вызовы методов для перечисления по объектам заменяются арифметикой указателя с использованием протокола NSFastEnumeration.

Расширения классов

Расширение класса имеет тот же синтаксис, что и объявление категории без имени категории, а объявленные в нем методы и свойства добавлены непосредственно к основному классу., с тем преимуществом, что для расширений классов компилятор проверяет, что все объявленные в частном порядке методы действительно реализованы.

Последствия для разработки какао

Разработаны все приложения Objective-C для macOS, которые используют вышеуказанные улучшения для Objective-C 2.0, несовместимы со всеми операционные системы до 10.5 (Leopard). Использование предложения в Mac OS X версии 10.4 или более ранней.

Блоки

Блоки - нестандартное расширение для Objective-C (и C и C ++ ), которое использует специальный синтаксис для создания замыканий. Блоки поддерживаются только в Mac OS X 10.6 "Snow Leopard" или новее, iOS 4 или новее, и GNUstep с libobjc2 1.7 и компиляцией с clang 3.1 или позже.

#include #include typedef int (^ IntBlock) (); IntBlock MakeCounter (int start, int increment) {__block int i = start; return Block_copy (^ {int ret = i; i + = приращение; return ret;}); } int main (void) {IntBlock mycounter = MakeCounter (5, 2); printf ("Первый вызов:% d \ n", mycounter ()); printf ("Второй вызов:% d \ n", mycounter ()); printf ("Третий вызов:% d \ n", mycounter ()); / * поскольку он был скопирован, его также необходимо освободить * / Block_release (mycounter); возврат 0; } / * Вывод: Первый вызов: 5 Второй вызов: 7 Третий вызов: 9 * /

Modern Objective-C

Со временем Apple добавила некоторые дополнительные функции в Objective 2.0. Дополнения применимы только к "компилятору Apple LLVM ", то есть к интерфейсу языка clang. Как ни странно, управление версиями, используемое Apple, отличается от восходящего потока LLVM; см. XCode § Version Toolchain для перевода на номера версий LLVM с открытым исходным кодом.

Автоматический подсчет ссылок

Автоматический подсчет ссылок (ARC) - это функция времени компиляции.. В отличие от сборки мусора, которая происходит во время выполнения, ARC устраняет накладные расходы отдельного процесса, управляющего счетчиками хранения. ARC и ручное управление памятью не исключают друг друга; Программисты могут использовать код без ARC в рамках программы ARC, отключив ARC для отдельных файлов. Xcode также может попытаться автоматически обновить проект до ARC.

ARC был представлен в LLVM 3.0. Это переводится в XCode 4.2 (2011) или компилятор Apple LLVM 3.0.

Литералы

Среда выполнения NeXT и Apple Obj-C уже давно включает краткий способ создания новых строк с использованием буквального синтаксис @ "новая строка", или пойти к константам CoreFoundation kCFBooleanTrueи kCFBooleanFalseдля NSNumberс логическими значениями. Использование этого формата избавляет программиста от необходимости использовать более длинный initWithStringили аналогичные методы при выполнении определенных операций.

При использовании Apple LLVM compiler 4.0 (XCode 4.4) или более поздней версии массивы, словари и числа (NSArray, NSDictionary, NSNumberклассы) также могут быть созданы с использованием буквального синтаксиса вместо методов. (Компилятор Apple LLVM 4.0 преобразуется в LLVM с открытым исходным кодом и Clang 3.1.)

Пример без литералов:

NSArray * myArray = [NSArray arrayWithObjects: object1, object2, object3, nil]; NSDictionary * myDictionary1 = [NSDictionary dictionaryWithObject: someObject forKey: @ "key"]; NSDictionary * myDictionary2 = [NSDictionary dictionaryWithObjectsAndKeys: object1, key1, object2, key2, nil]; NSNumber * myNumber = [NSNumber numberWithInt: myInt]; NSNumber * mySumNumber = [NSNumber numberWithInt: (2 + 3)]; NSNumber * myBoolNumber = [NSNumber numberWithBool: ДА];

Пример с литералами:

NSArray * myArray = @ [object1, object2, object3]; NSDictionary * myDictionary1 = @ {@ "key": someObject}; NSDictionary * myDictionary2 = @ {ключ1: объект1, ключ2: объект2}; NSNumber * myNumber = @ (myInt); NSNumber * mySumNumber = @ (2 + 3); NSNumber * myBoolNumber = @YES; NSNumber * myIntegerNumber = @ 8;

Однако, отличие от строковых литералов, которые компилируются в константы в исполняемом файле, эти литералы компилируются в код, эквивалентный вышеуказанным вызовам методов. В частности, при ручном управлении памятью с подсчетом ресурсов эти объекты освобождаются автоматически, что требует дополнительной осторожности, например, при использовании с функционально-статическими переменными или другими видами глобальных переменных.

Индексы

При использовании Apple LLVM compiler 4.0 или более поздней версии массивы и словари (NSArrayи NSDictionaryклассы) можно манипулировать с помощью индекс. Индексы можно использовать для извлечения значений из индексов (массив) или ключей (словарь), а с изменяемыми объектами также можно использовать для установки объектов в индексы или ключи. В коде индексирование представляется с помощью скобок [].

Пример без индекса:

id object1 = [someArray objectAtIndex: 0]; id object2 = [someDictionary objectForKey: @ "ключ"]; [someMutableArray replaceObjectAtIndex: 0 withObject: object3]; [someMutableDictionary setObject: object4 forKey: @ "ключ"];

Пример с индексированием:

id object1 = someArray [0]; id object2 = someDictionary [@ "ключ"]; someMutableArray [0] = объект3; someMutableDictionary [@ "ключ"] = объект4;

«Современный» синтаксис Objective-C (1997)

После покупки NeXT Apple были предприняты попытки сделать язык более приемлемым для программистов, более знакомых с Java, чем Smalltalk. Одна из этих попыток заключалась в том, чтобы внедрить то, что в то время называлось «Современный синтаксис» для Objective-C (в отличие от текущего «классического» синтаксиса). Поведение не изменилось, это был просто альтернативный синтаксис. Вместо написания метода метода типа

object = [[MyClass alloc] init]; [объект firstLabel: param1 secondLabel: param2];

Вместо этого он был записан как

object = (MyClass.alloc).init; object.labels (param1, param2);

Аналогично, объявления пошли из формы

- (void) firstLabel: (int) param1 secondLabel: (int) param2; От

до

- (пустые) метки (int param1, int param2);

Этот «современный» синтаксис больше не поддерживается в текущих диалектах языка Objective-C.

mulle-objc

Проект mulle-objc - это еще одна повторная реализация Objective-C. Он поддерживает компиляторы GCC или Clang / LLVM в качестве бэкэндов. Он отличается от других сред выполнения с точки зрения синтаксиса, семантики и совместимости с ABI. Он поддерживает Linux, FreeBSD и Windows.

Portable Object Compiler

Помимо реализации GCC / NeXT / Apple, которая добавила несколько расширений к исходному Stepstone, существует еще одна реализация с открытым исходным кодом Objective-C, называемая Portable Object Compiler. Набор расширений, реализуемых Portable Object Compiler, отличается от реализации GCC / NeXT / Apple; в частности, он включает блоки типа Smalltalk для Objective-C, но в нем отсутствуют протоколы и категории, две функции, широко используемые в OpenStep и его производных и родственниках. В, POC представляет собой более старую стадию развития языка, предшествующую NeXT, аналогичную книге Брэда Кокса 1991 года.

Он также включает библиотеку времени выполнения под названием ObjectPak, которая основана на исходной библиотеке Cox ICPak101 (в свою очередь, в свою очередь, производным от библиотеки классов Smalltalk-80) и радикально отличается от OpenStep FoundationKit.

GEOS Objective-C

В системе PC GEOS использовался язык программирования, известный как GEOS Objective-C или goc ; Несмотря на схожесть названий, эти два языка похожи только в общей концепции и использовании ключевых слов с префиксом @.

Clang

Пакет компиляторов Clang, часть проекта LLVM, реализует Objective-C и другие языки. После того, как GCC 4.3 (2008) перешел на GPLv3, Apple отказалась от него в пользу clang, компилятора, который он имеет больше юридических полномочий изменять. В результате многие современные функции языка Objective-C поддерживаются только Clang.

Схема управления версиями Apple для своего "компилятора LLVM" на основе clang отличается от управления версиями LLVM с открытым исходным кодом. См. XCode § Toolchain версии для перевода

GNU, GNUstep и WinObjC

Проект GNU долгое время интересовался платформой для переноса NeXT и программы Obj-C в. Журнал изменений для каталога libobjc в GCC предполагает, что он существовал до 1998 года (GCC 2.95), а его README указывает на переписывание в 1993 году (GCC 2.4).

Был выпущен исходный код внешнего интерфейса NeXT поскольку он был создан как часть GCC, выпущена Общественная лицензия GNU, которая заставляет делать это производными работами. Apple продолжила эту традицию, выпустив свою вилку GCC до версии 4.2.1, после чего отказалась от компилятора. Сопровождающие GCC приняли изменения, но не вложили много средств в поддержку новых функций, таких как язык Objective-C 2.0.

Разработчики GNUstep, заинтересованные в новом языке, разделили GCC libobjc на Независимый от GCC проект под названием libobjc2 в 2009 году. Они также организовали использование среды выполнения с Clang, чтобы воспользоваться преимуществами нового синтаксиса языка. В то же время GCC продвигался медленно, но в GCC 4.6.0 (2011) они также перешли на Objective-C 2.0 в своей libobjc. Документация GNUstep предполагает, что в реализации GCC по-прежнему отсутствует поддержка блоков, нестабильных переменных и более нового ARC.

Microsoft разделила libobjc2 на часть WinObjC, моста iOS. для универсальной платформы Windows в 2015 году. В сочетании с собственной реализацией Cocoa Touch и базовыми API-интерфейсами проект позволяет повторно использовать код приложения iOS внутри приложений UWP.

В Windows инструменты разработки Objective-C доступны для загрузки на веб-сайте GNUStep. Система разработки GNUStep состоит из следующих пакетов: GNUstep MSYS System, GNUstep Core, GNUstep Devel, GNUstep Cairo, ProjectCenter IDE (как Xcode, но не такой сложный), Gorm (Interface Builder Like Xcode NIB builder). Эти двоичные установщики не обновлялись с 2016 года, поэтому было бы лучше просто установить их, собрав вместо них Cygwin или MSYS2.

Использование библиотеки

Сегодня Objective-C часто используется в тандеме с фиксированной библиотекой стандартных объектов (часто известной как «комплект» или «структура»), например Какао., GNUstep или. Эти библиотеки часто поставляются с операционной системой: библиотеки GNUstep часто поставляются с дистрибутивами на основе Linux, а Cocoa поставляется с macOS. Программист не обязан наследовать функциональность существующего базового класса (NSObject / OFObject). Objective-C позволяет объявлять новые корневые классы, которые не наследуют никаких существующих функций. Первоначально среды программирования на основе Objective-C обычно предлагали класс Object в качестве базового класса, от которого унаследованы почти все остальные классы. С введением OpenStep NeXT создал новый базовый класс с именем NSObject, который предлагал дополнительные функции по сравнению с Object (например, упор на использование ссылок на объекты и подсчет ссылок вместо необработанных указателей). Почти все классы в Какао наследуются от NSObject.

Переименование не только служило для дифференциации нового поведения классов по умолчанию в API OpenStep, но и позволяло использовать код, использующий Object - исходный базовый класс, используемый в NeXTSTEP (и, более или менее, другой Objective- Библиотеки классов C) - сосуществовать в одной среде выполнения с кодом, который использовал NSObject (с некоторыми ограничениями). Введение двухбуквенного префикса также стало упрощенной формой пространств имен, которых нет в Objective-C. Использование префикса для создания неформального идентификатора упаковки стало неформальным стандартом кодирования в сообществе Objective-C и продолжается по сей день.

В последнее время начали появляться менеджеры пакетов, такие как CocoaPods, который стремится быть одновременно менеджером пакетов и репозиторием пакетов. Большой объем кода Objective-C с открытым исходным кодом, который был написан за последние несколько лет, теперь можно установить с помощью CocoaPods.

Анализ языка

Реализации Objective-C используют тонкую систему времени выполнения, написанную на C, что немного увеличивает размер приложения. Напротив, большинство объектно-ориентированных систем в то время, когда они были созданы, использовали большие среды выполнения виртуальных машин. Программы, написанные на Objective-C, как правило, не намного больше, чем размер их кода и библиотек (которые, как правило, не нужно включать в дистрибутив программного обеспечения), в отличие от систем Smalltalk, в которых был большой объем памяти. раньше просто открывал окно. Приложения Objective-C, как правило, больше, чем аналогичные приложения C или C ++, потому что динамическая типизация Objective-C не позволяет вырезать или встраивать методы. Поскольку у программиста есть такая свобода делегировать, переадресовывать вызовы, создавать селекторы на лету и передавать их системе времени выполнения, компилятор Objective-C не может предположить, что можно безопасно удалить неиспользуемые методы или встроенные вызовы.

Точно так же язык может быть реализован поверх существующих компиляторов C (в GCC, сначала как препроцессор, затем как модуль), а не как новый компилятор. Это позволяет Objective-C использовать огромную существующую коллекцию кода C, библиотек, инструментов и т. Д. Существующие библиотеки C могут быть заключены в Objective-C оболочки для обеспечения интерфейса в стиле объектно-ориентированного программирования. В этом аспекте он похож на библиотеку GObject и язык Vala, которые широко используются при разработке приложений GTK.

Все эти практические изменения снизили порог входа , что, вероятно, стало самой большой проблемой для широкого распространения Smalltalk в 1980-х.

Распространенной критикой является то, что Objective-C не имеет языковой поддержки для пространств имен. Вместо этого программисты вынуждены добавлять префиксы к своим именам классов, которые традиционно короче имен пространств имен и, следовательно, более подвержены конфликтам. Начиная с 2007 года, все классы и функции macOS в среде программирования Какао имеют префикс «NS» (например, NSObject, NSButton), чтобы идентифицировать их как принадлежащие ядру macOS или iOS; "NS" происходит от имен классов, определенных при разработке NeXTSTEP.

Поскольку Objective-C является строгим надмножеством C, он не рассматривает примитивные типы C как объекты первого класса.

В отличие от C ++, Objective-C не поддерживает перегрузку оператора . Также в отличие от C ++, Objective-C позволяет объекту напрямую наследовать только от одного класса (запрещая множественное наследование ). Однако в большинстве случаев категории и протоколы могут использоваться в качестве альтернативных способов достижения тех же результатов.

Поскольку Objective-C использует динамическую типизацию во время выполнения и поскольку все вызовы методов являются вызовами функций (или, в некоторых случаях, системными вызовами), многие общие оптимизации производительности не могут быть применены к методам Objective-C (например: встраивание, постоянное распространение, межпроцедурные оптимизации и скалярная замена агрегатов). Это ограничивает производительность абстракций Objective-C по сравнению с аналогичными абстракциями в таких языках, как C ++, где такие оптимизации возможны.

Управление памятью

Первые версии Objective-C не поддерживали сборку мусора. В то время это решение было предметом споров, и многие люди считали, что долгие «мертвые времена» (когда Smalltalk выполнял сбор данных) сделали всю систему непригодной для использования. Некоторые сторонние реализации добавили эту функцию (в первую очередь GNUstep с использованием Boehm ), и Apple реализовала ее начиная с Mac OS X v10.5. Однако в более поздних версиях macOS и iOS сборка мусора устарела в пользу автоматического подсчета ссылок (ARC), представленного в 2011 году.

С ARC компилятор вставляет сохраняет и автоматически выпускать вызовы в код Objective-C на основе статического анализа кода. Автоматизация избавляет программиста от необходимости писать код управления памятью. ARC также добавляет слабые ссылки на язык Objective-C.

Философские различия между Objective-C и C ++

Дизайн и реализация C ++ и Objective-C представляют фундаментальные различные подходы к расширению C.

В дополнение к стилю процедурного программирования C, C ++ напрямую поддерживает определенные формы объектно-ориентированного программирования, общего программирования и метапрограммирование. C ++ также поставляется с большой стандартной библиотекой, которая включает несколько контейнерных классов. Аналогичным образом, Objective-C добавляет в C. объектно-ориентированное программирование, динамическую типизацию и отражение. Objective-C не предоставляет стандартную библиотеку как таковую, но в большинстве мест, где используется Objective-C, он используется с OpenStep -подобной библиотекой, такой как OPENSTEP, Cocoa или GNUstep, который обеспечивает функциональность, аналогичную стандартной библиотеке C ++.

Одно заметное отличие состоит в том, что Objective-C обеспечивает поддержку среды выполнения для отражающих функций, тогда как C ++ добавляет лишь небольшую поддержку среды выполнения в C. В Objective-C можно запрашивать объект. о его собственных свойствах, например, ответит ли он на определенное сообщение. В C ++ это невозможно без использования внешних библиотек.

Использование отражения является частью более широкого различия между динамическими (во время выполнения) функциями и статическими (во время компиляции) функциями языка. Хотя Objective-C и C ++ используют сочетание обеих функций, Objective-C определенно ориентирован на решения во время выполнения, а C ++ ориентирован на решения во время компиляции. Противоречие между динамическим и статическим программированием включает многие из классических компромиссов в программировании: динамические функции добавляют гибкости, статические функции добавляют скорость и проверку типов.

Общее программирование и метапрограммирование могут быть реализованы на обоих языках с использованием полиморфизма времени выполнения. В C ++ это принимает форму виртуальных функций и идентификации типа среды выполнения, тогда как Objective-C предлагает динамическую типизацию и отражение. И Objective-C, и C ++ поддерживают полиморфизм времени компиляции (универсальные функции ), а Objective-C добавил эту функцию только в 2015 году.

См. Также

Ссылки

Дополнительная литература

Внешние ссылки

В Викиучебнике есть книга на тему: Программирование на Objective-C
Последняя правка сделана 2021-06-01 07:23:16
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте