Статьи

Изучите Цель-C: День 2

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

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

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

Все еще немного нечетко? Еще одна замечательная аналогия — это печенье и резак печенья. Класс является печеньем, а объект — печеньем.

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

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

Итак, у нас есть «экземпляр» автомобиля, теперь, что нам с ним делать? Ну, мы ездим на нем и заправляем его бензином, между прочим. Вождение и заправка бензином относятся только к автомобилям, которые мы используем, а это означает, что когда мы заправляем автомобиль или едем на автомобиле, мы воздействуем только на один случай, а не на все автомобили в мире. Поэтому заполнение экземпляра автомобиля считается методом экземпляра . Это то, что мы делаем для нашего экземпляра и только для нашего экземпляра.

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

Многие из этих принципов становятся более понятными при использовании, поэтому давайте рассмотрим немного синтаксиса.

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

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

Итак, имея в виду наш предыдущий пример, мы будем взаимодействовать с нашим экземпляром автомобиля, чтобы добавить бензина в бак;

В приведенном выше примере предполагается, что мы создали экземпляр класса Car и назвали его «dansCar». Затем мы передаем сообщение «addGas» объекту «dansCar», что эквивалентно вызову функции. На другом языке эта строка может выглядеть так:

Допустим, в нашем классе автомобилей есть бензобак, который хранится в процентах. Например, если бензобак на 50%, то он наполовину полон, а если на 100%, это означает, что он полон до краев. Теперь, если мы хотим узнать, сколько газа находится в баке, мы не просто напрямую получаем эту информацию из атрибута. Вместо этого мы использовали бы метод доступа для доступа к внутренней переменной для нас. Точно так же, когда мы хотим заполнить бак, мы не просто присваиваем атрибуту бензобака новый процент, мы используем установщик, чтобы обновить атрибут для нас. Этот процесс известен как инкапсуляция данных.

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

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

Когда вы создадите простой класс в Objective-C или поработаете с ним, вы увидите, что по умолчанию у него есть два файла. Одним из них является файл реализации, который является файлом, который заканчивается суффиксом .m, и файлом интерфейса, который является файлом, который заканчивается суффиксом .h.

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

Далее мы заявляем, что это интерфейс для Автомобиля, но мы также помещаем NSObject в эту декларацию. Добавление «: NSObject» означает, что класс Car наследуется от класса NSObject. Мы поговорим больше о наследовании в следующем уроке.

Наша переменная экземпляра «fillLevel» объявляется следующей, и мы указываем, что она относится к типу данных «float», поэтому мы можем легко представить процент.

Следующая строка объявляет наш метод «addGas». «-» указывает, что это метод экземпляра, а не метод класса. Часть «(void)» означает, что метод не вернет ничего, когда он завершит выполнение. Если класс собирался вернуть целое число, это было бы изменено на «(int)» и то же самое для любого другого типа данных. Наконец, мы завершаем объявление метода точкой с запятой.

Реализация в этом случае содержит способ добавления газа в бак. Мы также импортируем Car.h, который является файлом интерфейса. Там, где находится наш метод addGas, мы могли бы добавить гораздо больше методов, но сегодняшняя задача — просто помочь вам понять, как работают классы, а не сделать полноценный класс.

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

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