Цель-C - Objective-C

Цель-C
СемьяC
РазработаноТом Лав и Брэд Кокс
Впервые появился1984; 36 лет назад (1984)
Стабильный выпуск
2.0[1]
Печатная дисциплинастатический, динамичный, слабый
Операционные системыКроссплатформенность
Расширения имени файла.h, .m, .mm, .M
Интернет сайтdeveloper.apple.com
Основной реализации
Лязг, GCC
Под влиянием
C, Болтовня
Под влиянием
Groovy, Ява, Nu, Цель-J, ТОМ, Быстрый[2]

Цель-C это общее назначение, объектно-ориентированный язык программирования это добавляет Болтовня -стиль обмен сообщениями к C язык программирования. Это был основной язык программирования, поддерживаемый яблоко за macOS, iOS, и их соответствующие интерфейсы прикладного программирования (API), Какао и Какао Touch, до введения Быстрый в 2014.[3]

Первоначально язык был разработан в начале 1980-х годов. Позже он был выбран в качестве основного языка, используемого Следующий для своего Следующий шаг операционная система, из которой macOS и iOS являются производными.[4] Переносимые программы Objective-C, которые не используют библиотеки Apple или те, которые используют части, которые могут быть перенесены или переопределены для других систем, также могут быть скомпилированы для любой системы, поддерживаемой Коллекция компиляторов GNU (GCC) или Лязг.

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

История

Objective-C был создан в первую очередь Брэд Кокс и Том Лав в начале 1980-х в своей компании Productivity Products International.[5]

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

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

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

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

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

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

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

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

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

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

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

Синтаксис

Objective-C - это тонкий слой поверх C и является "строгим суперсет "of C, что означает, что можно скомпилировать любую программу C с помощью компилятора Objective-C и свободно включать код языка C в класс Objective-C.[12][13][14][15][16][17]

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

Сообщения

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

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

объект->метод(аргумент);

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

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

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

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

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

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

Интерфейс

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

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

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

@интерфейс имя класса : имя суперкласса {  // переменные экземпляра}+ 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;@конец

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

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

учебный класс имя класса : общественный имя суперкласса {защищенный:  // переменные экземпляраобщественный:  // Классовые (статические) функции  статический пустота *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 = дефолт);};

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

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

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

- (пустота)setRangeStart:(int)Начните конец:(int)конец;- (пустота)importDocumentWithName:(NSString *)имя      withSpecifiedPreferences:(Предпочтения *)префы                    beforePage:(int)insertPage;

Производным от определения интерфейса является категория, что позволяет добавлять методы к существующим классам.[22]

Выполнение

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

@выполнение имя класса+ (return_type)classMethod {  // выполнение}- (return_type)instanceMethod {  // выполнение}@конец

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

- (int)метод:(int)я {  возвращаться [себя квадратный корень:я];}
int функция(int я) {  возвращаться квадратный корень(я);}

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

- (пустота)changeColorToRed:(плавать)красный зеленый:(плавать)зеленый синий:(плавать)синий {  //... Выполнение ...}// Вызывается так:[myColor changeColorToRed:5.0 зеленый:2.0 синий:6.0];

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

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

Создание

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

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

MyObject *фу = [[MyObject выделить] в этом];

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

MyObject *фу = [[MyObject выделить] initWithString:myString];

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

MyObject *фу = [MyObject новый];

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

MyObject *фу = [MyObject объект];MyObject *бар = [MyObject objectWithString:@ "Википедия :)"];

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

В в этом message выполняет настройку экземпляра при создании. В в этом метод часто записывается так:

- (я бы)в этом {    себя = [супер в этом];    если (себя) {        // здесь выполняем инициализацию объекта    }    возвращаться себя;}

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

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

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

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

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

Протоколы

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

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

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

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

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

Синтаксис

@protocol NSLocking- (пустота)замок;- (пустота)разблокировать;@конец

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

@интерфейс NSLock : NSObject <NSLocking>// ...@конец

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

Динамический набор текста

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

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

- (пустота)setMyValue:(я бы)фу;

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

- (пустота)setMyValue:(я бы<NSCopying>)фу;

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

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

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

- (пустота)setMyValue:(NSNumber<NSCopying> *)фу;

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

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

Пересылка

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

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

  • методы пересылки:
    - (retval_t)вперед:(SEL)сел аргументы:(arglist_t)аргументы; // с GCC- (я бы)вперед:(SEL)сел аргументы:(marg_list)аргументы; // с системами NeXT / Apple
  • методы действия:
    - (retval_t)Performv:(SEL)сел аргументы:(arglist_t)аргументы; // с GCC- (я бы)Performv:(SEL)сел аргументы:(marg_list)аргументы; // с системами NeXT / Apple

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

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

Пример

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

Forwarder.h
#import @интерфейс Экспедитор : Объект {  я бы получатель; // Объект, которому мы хотим переслать сообщение.}// Методы доступа.- (я бы)получатель;- (я бы)setRecipient:(я бы)_получатель;@конец
Экспедитор.m
#import "Forwarder.h"@выполнение Экспедитор- (retval_t)вперед:(SEL)сел аргументы:(arglist_t)аргументы {  /*  * Проверьте, действительно ли получатель отвечает на сообщение.  * Это может быть или нежелательно, например, если получатель  * в свою очередь не отвечает на сообщение, возможно, пересылка  * сам.  */  если ([получатель RespondsToSelector:сел]) {    возвращаться [получатель перформанс:сел аргументы:аргументы];  } еще {    возвращаться [себя ошибка:«Получатель не отвечает»];  }}- (я бы)setRecipient:(я бы)_получатель {  [получатель автоматический выпуск];  получатель = [_получатель удерживать];  возвращаться себя;}- (я бы)получатель {  возвращаться получатель;}@конец
Recipient.h
#import // Простой объект Recipient.@интерфейс Получатель : Объект- (я бы)Привет;@конец
Recipient.m
#import "Recipient.h"@выполнение Получатель- (я бы)Привет {  printf("Получатель передает привет! п");  возвращаться себя;}@конец
main.m
#import "Forwarder.h"#import "Recipient.h"int главный(пустота) {  Экспедитор *экспедитор = [Экспедитор новый];  Получатель *получатель = [Получатель новый];  [экспедитор setRecipient:получатель]; // Устанавливаем получателя.  /*  * Наблюдать, пересылка не отвечает на приветственное сообщение! Так и будет  * быть направленным.Все нераспознанные методы будут перенаправлены на  * получатель  * (если получатель на них отвечает, как написано в Экспедиторе)  */  [экспедитор Привет];  [получатель релиз];  [экспедитор релиз];  возвращаться 0;}

Примечания

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

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

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

$ ./a.outRecipient передает привет!

Категории

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

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

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

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

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

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

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

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

В этом примере создается Целое число class, определив сначала базовый класс только с методы доступа реализовано, и добавив две категории, Арифметика и Отображать, которые расширяют базовый класс. Хотя категории могут получить доступ к закрытым членам данных базового класса, часто хорошей практикой является доступ к этим частным членам данных с помощью методов доступа, что помогает сохранять категории более независимыми от базового класса. Реализация таких средств доступа - типичное использование категорий. Другой - использовать категории для добавления методов к базовому классу. Однако использование категорий для переопределения подкласса не считается хорошей практикой, также известной как исправление обезьяны. Неформальные протоколы реализованы как категория на основе NSObject учебный класс. По соглашению файлы, содержащие категории, расширяющие базовые классы, получат имя BaseClass + ExtensionClass.h.

Integer.h
#import @интерфейс Целое число : Объект {  int целое число;}- (int)целое число;- (я бы)целое число:(int)_integer;@конец
Integer.m
#import "Integer.h"@выполнение Целое число- (int) целое число {  возвращаться целое число;}- (я бы) целое число: (int) _integer {  целое число = _integer;  возвращаться себя;}@конец
Целое число + Arithmetic.h
#import "Integer.h"@интерфейс Целое число (Арифметика)- (я бы) Добавить: (Целое число *) добавить;- (я бы) суб: (Целое число *) вычитаемое;@конец
Целое число + Арифметика. M
# import "Integer + Arithmetic.h"@выполнение Целое число (Арифметика)- (я бы) Добавить: (Целое число *) добавить {  возвращаться [себя целое число: [себя целое число] + [добавить целое число]];}- (я бы) суб: (Целое число *) вычитаемое {  возвращаться [себя целое число: [себя целое число] - [вычитаемое целое число]];}@конец
Целое число + Display.h
#import "Integer.h"@интерфейс Целое число (Отображать)- (я бы) шоузвезды;- (я бы) шоуинт;@конец
Целое число + Display.m
# import "Integer + Display.h"@выполнение Целое число (Отображать)- (я бы) шоузвезды {  int я, Икс = [себя целое число];  за (я = 0; я < Икс; я++) {    printf("*");  }  printf(" п");  возвращаться себя;}- (я бы) шоуинт {  printf("% d п", [себя целое число]);  возвращаться себя;}@конец
main.m
#import "Integer.h"#import "Integer + Arithmetic.h"#import "Integer + Display.h"int главный(пустота) {  Целое число *число1 = [Целое число новый], *число2 = [Целое число новый];  int Икс;  printf("Введите целое число:");  сканф("% d", &Икс);  [число1 целое число:Икс];  [число1 шоузвезды];  printf("Введите целое число:");  сканф("% d", &Икс);  [число2 целое число:Икс];  [число2 шоузвезды];  [число1 Добавить:число2];  [число1 шоуинт];  возвращаться 0;}

Примечания

Компиляция выполняется, например:

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

Можно поэкспериментировать, исключив #import "Integer + Arithmetic.h" и [num1 add: num2] строки и пропуск Целое число + арифметика. M в компиляции. Программа все равно будет работать. Это означает, что можно смешивать и сочетать при необходимости добавлены категории; если категории не нужно иметь какие-то способности, ее просто нельзя скомпилировать.

Позирует

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

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

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

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

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

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

Например,

@интерфейс CustomNSApplication : NSApplication@конец@выполнение CustomNSApplication- (пустота) setMainMenu: (NSMenu*) меню {  // делаем что-нибудь с меню}@конецclass_poseAs ([CustomNSApplication учебный класс], [NSApplication учебный класс]);

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

#импорт

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

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

// ФАЙЛ: hello.m#import int главный (int argc, const char * argv[]){    / * моя первая программа на Objective-C * /    NSLog(@"Привет, мир!  п");    возвращаться 0;}
# Компиляция командной строки для компилятора gcc и MinGW:$ gcc \    $(gnustep-config --objc-flags) \    -о привет \    привет.м \    -L / GNUstep / Система / Библиотека / Библиотеки \    -lobjc \    -lgnustep-base $ ./hello

Другие свойства

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

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

Языковые варианты

Цель-C ++

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

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

Objective-C 2.0

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

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

Вывоз мусора

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

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

Характеристики

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

@интерфейс Человек : NSObject {@public  NSString *имя;@частный  int возраст;}@свойство(копировать) NSString *имя;@свойство(только чтение) int возраст;- (я бы)initWithAge:(int)возраст;@конец

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

@выполнение Человек@синтезировать имя;- (я бы)initWithAge:(int)initAge {  себя = [супер в этом];  если (себя) {    // ПРИМЕЧАНИЕ: прямое присвоение переменной экземпляра, а не средство установки свойств    возраст = initAge;   }  возвращаться себя;}- (int)возраст {  возвращаться возраст;}@конец

Доступ к свойствам можно получить, используя традиционный синтаксис передачи сообщений, точечную нотацию или, в кодировке «ключ-значение», по имени с помощью методов «valueForKey:» / «setValue: forKey:».

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

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

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

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

int я;int propertyCount = 0;objc_property_t *propertyList =    class_copyPropertyList([персона учебный класс], &propertyCount);за (я = 0; я < propertyCount; я++) {  objc_property_t *thisProperty = propertyList + я;  const char *Имя свойства = property_getName(*thisProperty);  NSLog(@ "У человека есть свойство: '% s'", Имя свойства);}

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

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

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

Быстрый перебор

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

// Использование NSEnumeratorNSEnumerator *счетчик = [люди objectEnumerator];Человек *п;пока ((п = [счетчик nextObject]) != ноль) {  NSLog(@ "% @% i лет.", [п имя], [п возраст]);}
// Использование индексовза (int я = 0; я < [люди считать]; я++) {  Человек *п = [люди objectAtIndex:я];  NSLog(@ "% @% i лет.", [п имя], [п возраст]);}
// Используем быстрое перечислениеза (Человек *п в люди) {  NSLog(@ "% @% i лет.", [п имя], [п возраст]);}

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

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

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

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

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

Блоки

Blocks - нестандартное расширение для Objective-C (и C и C ++ ), который использует специальный синтаксис для создания закрытие. Блоки поддерживаются только в Mac OS X 10.6 «Снежный барс» или позже, iOS 4 или новее, и GNUstep с libobjc2 1.7 и компиляцией с лязгать 3.1 или новее.[42]

#включают <stdio.h>#включают <Block.h>typedef int (^IntBlock)();IntBlock MakeCounter(int Начните, int приращение) {	__блокировать int я = Начните;	возвращаться Block_copy( ^ {		int Ret = я;		я += приращение;		возвращаться Ret;	});}int главный(пустота) {	IntBlock mycounter = MakeCounter(5, 2);	printf("Первый звонок:% d п", mycounter());	printf("Второй звонок:% d п", mycounter());	printf("Третий звонок:% d п", mycounter());	/ * поскольку он был скопирован, его также необходимо освободить * /	Block_release(mycounter);	возвращаться 0;}/* Выход:Первый звонок: 5Второй звонок: 7Третий звонок: 9*/

Современный Objective-C

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

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

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

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

Литералы

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

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

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

NSArray *myArray = [NSArray arrayWithObjects:объект1,объект2,объект3,ноль];NSDictionary *myDictionary1 = [NSDictionary DictionaryWithObject:someObject forKey:@"ключ"];NSDictionary *myDictionary2 = [NSDictionary DictionaryWithObjectsAndKeys:объект1, key1, объект2, key2, ноль];NSNumber *мой номер = [NSNumber numberWithInt:myInt];NSNumber *mySumNumber= [NSNumber numberWithInt:(2 + 3)];NSNumber *myBoolNumber = [NSNumber numberWithBool:ДА];

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

NSArray *myArray = @[ объект1, объект2, объект3 ];NSDictionary *myDictionary1 = @{ @"ключ" : someObject };NSDictionary *myDictionary2 = @{ key1: объект1, key2: объект2 };NSNumber *мой номер = @(myInt);NSNumber *mySumNumber = @(2+3);NSNumber *myBoolNumber = @ДА;NSNumber *myIntegerNumber = @8;

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

Подписка

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

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

я бы объект1 = [someArray objectAtIndex:0];я бы объект2 = [someDictionary objectForKey:@"ключ"];[someMutableArray replaceObjectAtIndex:0 withObject:объект3];[someMutableDictionary setObject:объект4 forKey:@"ключ"];

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

я бы объект1 = someArray[0];я бы объект2 = someDictionary[@"ключ"];someMutableArray[0] = объект3;someMutableDictionary[@"ключ"] = объект4;

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

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

    объект = [[Мой класс выделить] в этом];    [объект firstLabel: param1 secondLabel: param2];

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

    объект = (Мой класс.выделить).в этом;    объект.этикетки ( param1, param2 );

Аналогичным образом декларации пошли из формы

    -(пустота) firstLabel: (int)param1 secondLabel: (int)param2;

к

    -(пустота) этикетки ( int param1, int param2 );

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

Mulle-objc

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

Компилятор переносимых объектов

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

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

GEOS Objective-C

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

Лязг

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

Схема управления версиями Apple для своего «компилятора LLVM» на основе clang отличается от системы управления версиями LLVM с открытым исходным кодом. Видеть XCode § Версии Toolchain для перевода[43]

GNU, GNUstep и WinObjC

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

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

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

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

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

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

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

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

Совсем недавно начали появляться менеджеры пакетов, такие как Какао-стручки, который должен быть одновременно менеджером пакетов и репозиторием пакетов. Большой объем кода 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 библиотека и Вала язык, которые широко используются при разработке GTK Приложения.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Смотрите также

Рекомендации

  1. ^ «Версии среды выполнения и платформы». Developer.apple.com. В архиве с оригинала от 20 июля 2016 г.. Получено 24 декабря, 2017.
  2. ^ Латтнер, Крис (3 июня 2014 г.). "Домашняя страница Криса Латтнера". Крис Латтнер. В архиве из оригинала 4 июня 2014 г.. Получено 3 июня, 2014. Язык Swift является продуктом неустанных усилий команды языковых экспертов, гуру документации, ниндзя по оптимизации компиляторов и невероятно важной внутренней группы, которая предоставила отзывы, чтобы помочь усовершенствовать и протестировать идеи. Конечно, он также очень выиграл от опыта, с трудом завоеванного многими другими языками в этой области, черпая идеи из Objective-C, Rust, Haskell, Ruby, Python, C #, CLU и слишком многих других, чтобы перечислить.
  3. ^ «Фреймворки приложений». Яблоко. Июнь 2014 г. В архиве с оригинала 16 февраля 2019 г.. Получено 13 февраля, 2019.
  4. ^ Сингх, Амит (декабрь 2003 г.). «Краткая история Mac OS X». Mac OS X Внутреннее устройство. В архиве из оригинала 14 мая 2012 г.. Получено 11 июня, 2012.
  5. ^ Гарлинг, Калеб. «Язык программирования iPhone стал третьим по популярности в мире». Проводной. В архиве из оригинала от 9 сентября 2013 г.. Получено 20 мая, 2013.
  6. ^ Вентк, Ричард (2009). Какао: Том 5 справочника разработчиков Apple Developer Series. Джон Уайли и сыновья. ISBN  978-0-470-49589-6. В архиве из оригинала 16 февраля 2017 г.. Получено 22 июля, 2016.
  7. ^ Бьянкуцци, Федерико; Уорден, Шейн (2009). Идеи программирования. O'Reilly Media, Inc. С. 242–246. ISBN  978-0-596-51517-1. В архиве из оригинала 17 февраля 2017 г.. Получено 22 июля, 2016.
  8. ^ Кокс, Брэд (1983). «Объектно-ориентированный прекомпилятор: программирование методов Smalltalk 80 на языке C». Уведомления ACM SIGPLAN. Нью-Йорк, штат Нью-Йорк: ACM. 18 (1). Дои:10.1145/948093.948095. S2CID  6975032. Получено 17 февраля, 2011.
  9. ^ "Common Lisp и Readline". В архиве из оригинала 6 сентября 2014 г.. Получено 15 сентября, 2014. Проблема впервые возникла, когда NeXT предложила распространить модифицированный GCC на две части и позволить пользователю связывать их. Джобс спросил меня, законно ли это. В то время мне казалось, что это так, следуя рассуждениям вроде того, что вы используете; но так как результат был очень нежелательным для свободных программ, я сказал, что мне нужно спросить юриста. То, что сказал адвокат, меня удивило; он сказал, что судьи сочтут такие схемы «уловками» и будут очень жестко к ним относиться. Он сказал, что судья спросит, действительно ли это одна программа, а не как она обозначена. Поэтому я вернулся к Джобсу и сказал, что, по нашему мнению, его план не разрешен GPL. Прямым результатом этого является то, что теперь у нас есть интерфейс для Objective C. Они хотели распространить анализатор Objective C как отдельный закрытый пакет для связи с серверной частью GCC, но, поскольку я не согласился, что это разрешено, они сделали его бесплатным.
  10. ^ «GNUstep: Введение». Разработчики GNUstep / Проект GNU. В архиве из оригинала от 6 августа 2012 г.. Получено 29 июля, 2012.
  11. ^ "Крестен Краб Торуп | LinkedIn". www.linkedin.com. В архиве из оригинала 15 июля 2014 г.. Получено 23 июня, 2016.
  12. ^ "Написать код Objective-C". apple.com. 23 апреля 2013 г. В архиве с оригинала от 24 декабря 2013 г.. Получено 22 декабря, 2013.
  13. ^ "Учебный курс Objective-C". В архиве с оригинала 11 февраля 2018 г.. Получено 11 февраля, 2018. Objective-C - это строгий надмножество ANSI C
  14. ^ «Цель исследования C». В архиве из оригинала 4 сентября 2014 г.. Получено 4 сентября, 2014. Objective-C - это объектно-ориентированное строгое надмножество C
  15. ^ Ли, Кейт (3 сентября 2013 г.). Pro Objective-C. Апресс. ISBN  9781430250500. В архиве из оригинала 14 мая 2018 г.. Получено 24 декабря, 2017 - через Google Книги.
  16. ^ «Теги для заголовков Objective-C». В архиве с оригинала от 1 апреля 2017 г.. Получено 11 февраля, 2018. Objective-C - это надмножество C
  17. ^ «Теперь доступен AppScan Source 8.7». В архиве из оригинала 3 февраля 2017 г.. Получено 11 февраля, 2018. Язык программирования Objective-C - это надмножество языка программирования C.
  18. ^ Apple, Inc. (19 октября 2009 г.). «Разрешение динамического метода». Руководство по программированию во время выполнения Objective-C. В архиве из оригинала 7 сентября 2010 г.. Получено 25 ноября, 2014.
  19. ^ Apple, Inc. (19 октября 2009 г.). «Как избежать ошибок обмена сообщениями». Язык программирования Objective-C. Архивировано из оригинал 8 сентября 2010 г.
  20. ^ "objc_msgSend - Среда выполнения Objective-C". Документация для разработчиков Apple. Получено 10 февраля, 2020.
  21. ^ «Обмен сообщениями со средой выполнения GNU Objective-C». Использование коллекции компиляторов GNU (GCC). Получено 10 февраля, 2020.
  22. ^ «Категория». Разработчик Apple (основные компетенции какао).
  23. ^ Далримпл, Марк; Кнастер, Скотт (27 июня 2012 г.). Изучите Objective-C на Mac. п. 9. ISBN  9781430241881. Расширение .m изначально обозначало "сообщения", когда впервые был представлен Objective-C, имея в виду центральную особенность Objective-C.
  24. ^ "Руководство по программированию на Objective-C". Apple Inc. В архиве из оригинала 4 апреля 2014 г.. Получено Двадцать первое октября, 2013.
  25. ^ "ACM SIGGRAPH 1983 Выпуск 8 - Smalltalk". Архивировано из оригинал 15 апреля 2009 г.. Получено 7 октября 2008.
  26. ^ «Методы расширения (Руководство по программированию на C #)». Microsoft. Октябрь 2010 г. В архиве из оригинала 11 июля 2011 г.. Получено 10 июля, 2011.
  27. ^ «Использование C ++ с Objective-C». Справочная библиотека Mac OS X. Архивировано из оригинал 5 сентября 2010 г.. Получено 10 февраля, 2010.
  28. ^ «Расширения языка Clang - документация Clang 3.5». Clang.llvm.org. В архиве из оригинала 24 февраля 2014 г.. Получено 16 апреля, 2014.
  29. ^ «Objective-C 2.0: больше подсказок». Lists.apple.com. 10 августа 2006 г. Архивировано с оригинал 18 июня 2009 г.. Получено 30 мая, 2010.
  30. ^ "Re: Objective-C 2.0". Lists.apple.com. Архивировано из оригинал 24 ноября 2010 г.. Получено 30 мая, 2010.
  31. ^ а б «Серия выпусков GCC 4.6 - Изменения, новые функции и исправления: Проект GNU: Фонд свободного программного обеспечения». Gcc.gnu.org. В архиве с оригинала 5 января 2018 г.. Получено 24 декабря, 2017.
  32. ^ а б c d "Часто задаваемые вопросы по ObjC2". GNUstep. Получено 6 января, 2020.
  33. ^ "Браузер исходного кода: objc4, 756.2". Открытый исходный код Apple. Получено 6 января, 2020.
  34. ^ Руководство по программированию сборки мусора: API сборки мусора В архиве 5 июня 2012 г., в WebCite (Веб-сайт разработчика Apple - введите «__strong»)
  35. ^ «Руководство по программированию сборки мусора: Введение в сборку мусора». Apple Inc. 3 октября 2011 г. В архиве из оригинала 5 июня 2012 г.. Получено 23 декабря, 2011.
  36. ^ «Серия Leopard Technology для разработчиков: Обзор Objective-C 2.0». Apple Inc. 6 ноября 2007 г. Архивировано с оригинал 24 июля 2010 г.. Получено 30 мая, 2010.
  37. ^ «Переход к примечаниям к версии ARC». Apple Inc. 17 июля 2012 г. В архиве из оригинала 5 июня 2012 г.. Получено 26 августа, 2012.
  38. ^ Майк Эш. «Пятничные вопросы и ответы 2013-09-27: ARM64 и вы». mikeash.com. В архиве из оригинала 26 апреля 2014 г.. Получено 27 апреля, 2014.
  39. ^ "Hamster Emporium: [объяснение объекта]: isa без указателя". Sealiesoftware.com. 24 сентября 2013 г. В архиве из оригинала 3 июня 2014 г.. Получено 27 апреля, 2014.
  40. ^ Apple, Inc. (2009 г.). «Быстрый перебор». apple.com. В архиве с оригинала 17 декабря 2009 г.. Получено 31 декабря, 2009.
  41. ^ Фонд свободного программного обеспечения, Inc. (2011 г.). «Серия выпусков GCC 4.6 - Изменения, новые функции и исправления». Gcc.gnu.org. В архиве с оригинала 2 декабря 2013 г.. Получено 27 ноября, 2013.
  42. ^ «Темы программирования блоков - Библиотека разработчика Mac». Apple Inc. 8 марта 2011 г. В архиве из оригинала 5 июня 2012 г.. Получено 28 ноября, 2012.
  43. ^ а б «Автоматический подсчет ссылок (ARC) Objective-C - документация Clang 11». Документация Clang. Получено 20 февраля, 2020. На данный момент имеет смысл редактировать этот документ путем выпуска его единственной реализации (и основного проекта) clang. «LLVM X.Y» относится к выпуску clang с открытым исходным кодом из проекта LLVM. «Apple X.Y» относится к предоставленной Apple версии компилятора Apple LLVM.
  44. ^ «Переход на ARC». Apple Inc. В архиве из оригинала 7 сентября 2011 г.. Получено 8 октября, 2012.
  45. ^ «Примечания к выпуску LLVM 3.0». releases.llvm.org.
  46. ^ а б «Программирование с помощью Objective-C: ценности и коллекции». Apple Inc. В архиве из оригинала 7 сентября 2011 г.. Получено 8 октября, 2012.
  47. ^ «Примечания к выпуску Clang 3.1». releases.llvm.org.
  48. ^ «Литералы Objective-C - документация Clang 3.5». Clang.llvm.org. В архиве из оригинала 6 июня 2014 г.. Получено 16 апреля, 2014.
  49. ^ Руководство разработчика Rhapsody, AP Professional, 1997, стр. 76–84.
  50. ^ «Переносимый объектный компилятор». Users.pandora.be. 1 января 1970 г. В архиве с оригинала 2 августа 2008 г.. Получено 30 мая, 2010.
  51. ^ Домашняя страница ООО "Компьютерная Компания Хлебная Коробка". Архивировано из оригинал 27 июля 2011 г.. Получено 8 декабря, 2010.
  52. ^ "gcc / libobjc". GitHub. gcc-зеркало. 6 января 2020 г.. Получено 6 января, 2020. среда выполнения была полностью переписана в gcc 2.4. Ранняя среда выполнения содержала несколько серьезных ошибок и была довольно неполной.
  53. ^ "API среды выполнения GNU Objective-C". Использование GCC. Получено 6 января, 2020.
  54. ^ "WinObjC на GitHub". В архиве с оригинала 2 декабря 2017 г.. Получено 13 февраля, 2018.
  55. ^ «Установщик GNUStep». В архиве из оригинала 17 февраля 2018 г.. Получено 14 февраля, 2018.
  56. ^ Apple, Inc. (22 августа 2006 г.). «Mac OS X Leopard - Xcode 3.0». apple.com. Архивировано из оригинал 24 октября 2007 г.. Получено 22 августа, 2006.
  57. ^ «Переход к примечаниям к версии ARC». Библиотека разработчика iOS. Developer.apple.com. В архиве из оригинала 7 сентября 2011 г.. Получено 16 апреля, 2014.

дальнейшее чтение

  • Кокс, Брэд Дж. (1991). Объектно-ориентированное программирование: эволюционный подход. Эддисон Уэсли. ISBN  0-201-54834-8.

внешняя ссылка