Содержание
Сегодня речь пойдет об одном из самых легендарных языков программирования – Objective-C. Это довольно сложный язык, с высоким порогом входа, на котором написано огромное количество приложений для macOS, iPad и iPhone.
iPhone тоже работает на Objective-C
Отличительная особенность этого языка состоит в том, что оно является расширением для другого языка программирования – С. Несмотря на то, что в последнее время Objective-C существенно уступает более прогрессивному, простому и удобному SWIFT, разработка Apple все еще остается актуальной и вызывает интерес.
Все началось в начале 70-х годов прошлого века. На заре программирования использовалась структурная парадигма написания кода. Такая архитектура подразумевала, что все программы строились на трех конструкциях: последовательность, ветвление и цикл (плюс подпрограммы). Подобная методология имела существенный недостаток, который становился все более очевидным по мере усложнения программ – код получался все более запутанным. Возникла необходимость в появлении какой-то технологии, которая бы позволила более рационально использовать код.
Книга о Smalltalk-80
Таким решением стал один из первых объектно-ориентированных языков с динамической типизацией – Smalltalk. Забавно, что, хотя он разрабатывался в семидесятых, его более или менее сформировавшаяся версия называлась Smalltalk-80 (наверное, его разработчики из научно-исследовательского центра Xerox PARC давали имя с прицелом на будущее). Уже в то время Smalltalk мог похвастаться возможностями, которые остаются актуальными и по сей день – у него был сборщик мусора, динамическая типизация. Программы, написанные на Smalltalk компилировались в байткод и выполнялись виртуальной машиной, что позволяло запускать код на любом оборудовании.
Взяв за основу главные принципы языка Smalltalk, был создан Objective-C. Создателем Objective-C считается Брэд Кокс, который старался в начале восьмидесятых сделать такой язык программирования, в котором была бы решена проблема повторяемости кода. Objective-C строился на базовых допущениях: класс – самостоятельный полноценный объект, передача сообщений между классами, динамическое типизирование. Самое главное, что отличало этот язык — гибкость. Программист мог писать код на С, а затем просто вставлять его в Objective-C и программа работала.
В 1985 году Стивом Джобсом, после его увольнения из Apple, была организована компания NeXT, в которую ушли работать несколько разработчиков из Apple. Стив Джобс выбрал для разработки будущих проектов Objective-C, который уже развивался несколько лет и был довольно перспективным проектом, да еще и кросс-совместим с языком С. Objective-C стал базовым языком программирования для операционной системы NeXTEP OS.
Интерфейс NeXTEP OS
В 1988 программисты NeXT разработали для Objective-C компилятор и SDK. А в 1992 году доработкой Objective-C и компилятора занялись также и участники проекта GNU, так GCC получил совместимость с Objective-C. С покупкой NeXT, Apple приобрела и этот SDK (включая компилятор, библиотеки и среду разработки). IDE получило название Xcode, а GUI – Interface Builder. Фреймворк Cocoa (API для macOS) сейчас является наиболее популярной средой разработки программ на Objective-C.
Современная ОС от Apple
В феврале 2008 Apple представил iPhone SDK 2.0, который позволял разрабатывать программы под платформу iOS. Это поспособствовало популяризации языка программирования Objective-C и дало возможность компании Стива Джобса быстро заполнить AppStore огромным числом приложений.
С Objective-C можно работать практически на любом дистрибутиве GNU/Linux через компилятор gobjc, включенный в набор компиляторов GNU Compiler Collection.
Разработка в Objective-C под ОС Windows возможна через бесплатные эмуляторы среды POSIX:
Когда программист С смотрит на код Objective-C он видит знакомый синтаксис с некоторыми дополнениями — квадратными скобками, значком “@
“, код, начинающийся с NS (наследие NeXTSTEP) и др
Самое простое приложение, которое выводит на экран текстовое сообщение, выглядит в Objective-C так:
int main(int argc, const char * argv[]) { @autoreleasepool { NSLog(@""Highload.tech""); } return 0; }
Когда нужно упаковать в объекте Objective-C целое, вещественное или логическое значение, используется класс NSNumber.
NSNumber *someNumber = [NSNumber numberWithInt:1];
с литеральным синтаксисом:
NSNumber *someNumber = @1;
Литеральный синтаксис распространяется на все типы данных:
NSNumber *intNumber = @1;
NSNumber *floatNumber = @2.5f;
NSNumber *doubleNumber = @3.14159;
NSNumber *boolNumber = @YES;
NSNumber *charNumber = @'a';
Переменные в Objective-C задаются следующим образом:
int hours = 24;
/* где int – это тип переменной, hours – имя, 24 – значение */
Если переменные состоят из двух слов, то второе слово пишется с большой буквы.
Когда в Objective-C идет обращение к какому-нибудь методу, это трактуется не как обращение к функции, а как отправка сообщения (с указанием аргументов и имени), аналогично тому, как это реализовано в Smalltalk. В этом заключается принципиальное отличие Objective-C от С++, который является функция-ориентированным языком. Поскольку Objective-C это объектно-ориентированный язык, вполне ожидаемо, что он соответствует основным принципам ООП:
Любому объекту, используемому в коде, можно отправить сообщение с любым содержанием. Объект сам может не обрабатывать сообщение. Вместо этого он может делегировать (переотправить) сообщение другому объекту, который уже его обработает. Объекты могут находиться в разных адресных пространствах и на разных ПК.
Все объекты классов Objective-C размещаются в динамической памяти. Каждый объект в Objective-C имеет собственный идентификатор id. Вместо id можно использовать и более привычное обозначение с явным указанием класса. В идентификаторах Objective-C нельзя использовать знаки препинания (символы @
, $
и %
). Кроме того, следует помнить, что Objective-C это регистрозависимый язык программирования.
Конструкция для отправки сообщений выглядит так:
[receiver method];
Аргументы в передаваемом сообщении разделяются двоеточием, параметров может быть сколько угодно:
[receiver methodAndFirstArgument: 20 andLastArgument: 30];
Когда требуется обратиться к методу с любым числом параметров, используется конструкция:
[receiver undefinedNumberParameters: oneParam, twoParam, threeParam, fourParam, fiveParam, sixParam, sevenParam];
Данный язык программирования допускает копирование любых объектов. Для этого, следует обратиться к методу copy, определённому в классе NSObject
. При создании копии вызывается метод copyWithZone
протокола NSCopying
. NSObject
не поддерживает данный протокол, поэтому протокол NSCopying
должен реализовываться в классах-наследниках. Различают два вида данной операции – поверхностная копия (shallow copy) и глубокая копия (deep copy). Отличие одного типа копирования от другого состоит в том, что при выполнении поверхностного копирования копируются не данные, а лишь указатель на объект с данными. При глубоком копировании копируется объект с данными.
Поскольку Objective-C представляет собой «обертку» для языка С или С++, в нем используются два типа файлов – заголовочные файлы (.h) и файлы реализации(.m).
Файлы, созданные при создании класса, могут выглядеть так:
//EOCPerson.h #import @interface EOCPerson:NSObject @property (nonatomic, copy) NSString *firstName @property (nonatomic, copy) NSString *lastName @end //EOCPerson.m #import "EOCPerson.h" @implementation EOCPerson //Реализация методов @end
Допустим, в классе Mycompany существует instance-переменная nameofcompany.
@interface Mycompany : NSObject { NSString *nameofcompany; }
Для доступа к ней оптимальнее всего обратиться к свойствам, которые появились в Objective-C 2.0. Чтобы объявить свойства используется ключевое слово @property.
@property (retain) NSString *nameofcompany;
В скобках перечисляются атрибуты доступа к instance-переменной.
К сожалению булевые данные в данном языке отсутствуют как тип. Поскольку для программирования это имеет критическое значение, его добавляют искусственно, как BOOL ( по факту это unsigned char). Он может принимать значения либо YES, либо NO (так реализовано в операционных системах NextStep, Mac OS X).
В других языках программирования, например, Java, они называются интерфейсами. Протокол выглядит как перечень описаний методов. Для задействования протокола объект обязан содержать реализации всех методов, описанных в протоколе. С помощью протоколов выделяются общие черты у разных объектов, а также передаются данные об объектах заранее неизвестных классов.
Пример описания протокола
@protocol TestProtocol -(void) test; -(void) testWithName: (NSString *) name; @end
В Objective-C используются циклы следующих типов:
Рассмотрим, как реализованы в Objective-C циклы. Напишем простенький код, который будет принимать строковые данные и разделять их на аргументы, нумеруя каждое введенное слово.
#include <stdio.h> int main (int argc, const char *argv[]) { for (int i = 0; i < argc; i++) { printf("arg %d : %s\n", i, argv[i]); } return 0; }
Пример цикла
Цикл обрабатывает текст, в результате чего программа выводит на печать новое слово, изменяя счетчик на единицу. Теперь скомпилируем программу и выполним в командной строке.
В Objective-C доступен контроль многопоточных вычислений. Используя директиву @synchronized () какую-то часть кода можно закрыть от одновременного исполнения паралельными потоками.
И, напоследок, рассмотрим несколько примеров приложений на Objective-C.
Код приложения, которое вычисляет корни квадратного уравнения:
#include #include int main() { int F, G, H, J; printf("F = "); scanf("%d", &F); if (F == 0) { printf("Ошибка с аргументами квадратного уравнения."); return 0; } printf("G = "); scanf("%d", &G); printf("H = "); scanf("%d", &H); J = G * G - 4 * F * H; if (J == 0) { printf("x = %f\n", -G / 2.0 / F); return 0; } if (J > 0) { printf("x1 = %f\nx2 = %f\n", (-G + sqrt(J)) / 2.0 / F, (-G - sqrt(J))/ 2.0 / F); } else { printf("x1 = (%f, %f)\nx2 = (%f, %f)\n", -G / 2.0 / F, sqrt(-J) / 2.0 / F, -G / 2.0 / F, -sqrt(-J) / 2.0 /F); } return 0; } Пример кода программы для перевода текста в регистр Camel Case #import <Foundation/Foundation.h> #define LETTERS @"ABCDFEGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" NSString *camelCase(NSString *s) { return [[[s capitalizedString] componentsSeparatedByCharactersInSet:[[NSCharacterSet characterSetWithCharactersInString:LETTERS] invertedSet]] componentsJoinedByString:@""]; } int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSLog(@"%@", camelCase(@"beliberda")); NSLog(@"%@", camelCase(@"primer-Dva ")); NSLog(@"%@", camelCase(@"!!! eto_cHto_esche_PRIMER?..")); [pool drain]; return 0; }
Сегодня этот язык программирования стремительно теряет популярность под давлением новых технологий, значительно уступая более простому и удобному SWIFT. Многие пророчат этому языку скорое забвение, поэтому изучать его или нет – решать только вам. Любой программист, владеющий языком С сможет разобраться с основами Objective-C за несколько часов. Для прочих желающих лучше понять тонкости этого языка программирования рекомендуем посмотреть видео ниже. В нем рассказывается как создавать классы, вызывать экземпляры классов, а также рассказывается о свойствах и методах классов.
Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…
Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…
Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…
В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…
Скрипт (англ. — сценарий), — это небольшая программа, как правило, для веб-интерфейса, выполняющая определенную задачу.…
Дедлайн (от англ. deadline — «крайний срок») — это конечная дата стачи проекта или задачи…