Расширение класса имеет некоторое сходство с категорией, но его можно добавить только в класс, для которого у вас есть исходный код во время компиляции (класс компилируется одновременно с расширением класса). Методы, объявленные расширением класса, реализованы в блоке @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 является необязательным, поскольку он используется по умолчанию. Для ясности вы можете использовать его при повторном выделении свойства.