Рубріки: Теория

Objective-C — объявляем категорию правильно (частая ошибка новичков)

Ігор Грегорченко

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


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

Синтаксис для объявления категории использует ключевое слово @interface, как и в стандартном описании класса Objective-C, но не указывает на наследование от подкласса. Вместо этого в круглых скобках указывается имя категории, как, например, здесь:

@interface ClassName (CategoryName)

@end

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

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

#import "ClassName.h"
 
@interface ClassName ( CategoryName )
// method declarations
@end

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

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

Характеристики категории и наш пример

Давайте сформулируем три главных свойства категории:

  • Категория может быть объявлена для любого класса, даже если у вас нет исходного кода реализации.
  • Любые методы, которые вы объявите в категории, будут доступны всем экземплярам исходного класса, а также любым подклассам исходного класса.
  • Во время выполнения нет никакой разницы между методом, добавленным категорией, и методом, реализованным исходным классом.

Теперь рассмотрим пример реализации категории.

Давайте добавим категорию к классу NSString в Cocoa. Эта категория позволит нам добавить новый метод getCopyRightString, который поможет нам вернуть строку копирайта.

Реализация этого показана ниже:

#import <Foundation/Foundation.h>

@interface NSString(MyAdditions)
+(NSString *)getCopyRightString;
@end

@implementation NSString(MyAdditions)

+(NSString *)getCopyRightString {
   return @"Copyright TutorialsPoint.com 2013";
}

@end

int main(int argc, const char * argv[]) {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   NSString *copyrightString = [NSString getCopyRightString];
   NSLog(@"Accessing Category: %@",copyrightString);
   
   [pool drain];
   return 0;
}

Теперь, когда мы скомпилируем и запустим программу, мы получим следующий вывод:

2013-09-22 21:19:12.125 Categories[340:303] Accessing Category: Copyright TutorialsPoint.com 2013

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

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

Подведение итогов

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

Расширения классов (про которые мы писали вот тут) похожи, но позволяют объявлять дополнительные необходимые API для класса не в основном блоке @interface класса, а в других местах.

Расширения классов подобны анонимным категориям, за исключением того, что объявленные в них методы должны быть реализованы в основном блоке @implementation для соответствующего класса. Используя компилятор Clang/LLVM 2.0, вы также можете объявлять свойства и переменные экземпляра в расширении класса.

Важно четко понимать эти отличия, чтобы не путать классы категорий и расширения (categories и extensions)!

Останні статті

Что такое прокси-сервер: пояснение простыми словами, зачем нужны прокси

Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…

21.11.2024

Что такое PWA приложение? Зачем необходимо прогрессивное веб-приложение

Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…

19.11.2024

Как создать игру на телефоне: программирование с помощью конструктора

Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…

17.11.2024

Google Bard: эффективный аналог ChatGPT

В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…

14.11.2024

Скрипт и программирование: что это такое простыми словами

Скрипт (англ. — сценарий), — это небольшая программа, как правило, для веб-интерфейса, выполняющая определенную задачу.…

12.11.2024

Дедлайн в разработке: что это такое простыми словами

Дедлайн (от англ. deadline — «крайний срок») — это конечная дата стачи проекта или задачи…

11.11.2024