Расширение класса против категории класса - PullRequest
77 голосов
/ 21 августа 2011

Расширения класса @interface Class () намного мощнее и могут вводить переменные в класс. Категории @interface Class (Category) не могут.

Какие еще различия существуют, и когда следует использовать категорию вместо расширения класса?

Ответы [ 4 ]

84 голосов
/ 21 августа 2011

Основное отличие состоит в том, что с расширением компилятор будет ожидать, что вы реализуете методы в вашем основном @implementation, тогда как с категорией у вас есть отдельный блок @implementation. Таким образом, вы должны в значительной степени использовать только расширение в верхней части вашего основного .m файла (кстати, единственное место, где вы должны заботиться о ivars) - это просто расширение .

24 голосов
/ 01 марта 2016

Расширение класса имеет некоторое сходство с категорией, но его можно добавить только в класс, для которого у вас есть исходный код во время компиляции (класс компилируется одновременно с расширением класса). Методы, объявленные расширением класса, реализованы в блоке @implementation для исходного класса, так что вы не можете, например, объявить расширение класса в классе платформы, таком как класс Touch Cocoa или Cocoa, например NSString.

Синтаксис для объявления расширения класса аналогичен синтаксису для категории и выглядит следующим образом:

@interface ClassName ()
@end

Поскольку в скобках не указано имя, расширения класса часто называют анонимными категориями.

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

@interface XYZAnimal () {
    id _someCustomInstanceVariable;
}
...
@end

ИМХО, лучше всего рассматривать расширения класса как закрытый интерфейс для класса. Основной интерфейс (в вашем файле .h) действует как открытый интерфейс, который определяет поведенческий контракт класса с другими классами.

Использование расширений классов для скрытия личной информации

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

Например, класс XYZPerson может добавить свойство с именем uniqueIdentifier, предназначенное для отслеживания такой информации, как номер социального страхования в США.

Обычно требуется большое количество документов, чтобы иметь уникальный идентификатор, назначенный человеку в реальном мире, поэтому интерфейс класса XYZPerson может объявить это свойство как доступное только для чтения, и предоставить некоторый метод, который запрашивает присвоение идентификатора, например :

@interface XYZPerson : NSObject
    ...
    @property (readonly) NSString *uniqueIdentifier;
    - (void)assignUniqueIdentifier;
@end

Чтобы класс XYZPerson мог изменять свойство внутри, имеет смысл переопределить свойство в расширении класса, которое определено в верхней части файла реализации для класса:

@property (readwrite) NSString *uniqueIdentifier;

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

5 голосов
/ 19 апреля 2015

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

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

0 голосов
/ 01 декабря 2015

расширение ios похоже на c #, абстрактный класс Java или интерфейс
ios категория похожа на расширение класса c #

...