Расширение класса против категории класса


82

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

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


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

Информацию о расширениях, используемых в Swift, см. В этом вопросе: stackoverflow.com/questions/24142829/…
Suragch

Ответы:


91

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


41
Расширение лучше всего подходит для частных методов, которые вы хотите объявить в своем .mфайле. Я использую его для этого все время. Категории более полезны, когда вы хотите сгруппировать свои методы в разные разделы - категории :) - или когда вы хотите добавить код в существующие классы, которые вы не создавали.
jtbandes

1
Вы также можете добавить дополнительное хранилище - это расширения классов, используя свойства.
Paul.s

23
Расширения классов также были специально разработаны для того, чтобы свойство могло быть публичным readonlyи частным readwrite. С категориями этого не сделать (сознательный выбор дизайна).
bbum

Почему Google использует категории для реализации частных методов вместо расширения? например code.google.com/p/gdata-objectivec-client/source/browse/trunk/…
Райан,

extension требует, чтобы все методы были реализованы в блоке @implementation, а также обеспечивает улучшение для переменных. Но мы в основном пытаемся использовать некоторые частные методы вместо использования частных переменных, поэтому в этом случае мы предпочитаем категорию вместо расширения
Анкит Такур

29

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

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

@interface ClassName ()
@end

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

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

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

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

Используйте расширения класса, чтобы скрыть личную информацию

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

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

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

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

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

@property (readwrite) NSString *uniqueIdentifier;

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


7

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

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


«это должно быть объявлено в основном блоке реализации». -> это должно быть «реализовано» в основном блоке реализации
Fawkes

Спасибо, доработал.
Julie Yu

0

Расширение ios похоже на C #, абстрактный класс java или интерфейс
категории ios аналогично расширению класса C #


Java не поддерживает методы расширения
someUser 03

К сожалению ! Скопируйте и вставьте опечатку. Категория iOS похожа на расширение класса C #.
Add080bbA 05

Можете добавить пример?
Педро Трухильо
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.