Что произойдет, если две категории ObjC переопределяют один и тот же метод? - программирование
Подтвердить что ты не робот

Что произойдет, если две категории ObjC переопределяют один и тот же метод?

Я знаю несколько правил относительно категорий Objective-C:

  • Методы категорий не должны переопределять существующие методы (класс или экземпляр).
  • Две разные категории, реализующие один и тот же метод для одного и того же класса, приведут к поведению undefined

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

@interface NSView (MyExtensions)
- (void)foo; // NSView category implementation
@end

@interface MyClass : NSView
{ }
@end

@interface MyClass (MyExtensions)
- (void)foo; // MyClass category implementation
@end

С определенными интерфейсами, какой метод будет выполняться при запуске следующего кода?

MyClass * instance = [[MyClass alloc] initWith...];
[instance foo];
[instance release];

Примечание. С моим компилятором реализация MyClass имеет приоритет, но я не уверен, что это гарантировано, или просто один конкретный вкус поведения undefined.

4b9b3361

Ответ 1

Каждый метод каждого класса имеет реализацию. Категория добавляет или заменяет метод для определенного класса. Это означает, что поведение, которое вы видите, где MyClass имеет один foo, а NSView имеет другой foo, хорошо определен. Любой экземпляр MyClass будет иметь другой foo, чем любой экземпляр NSView, который не является MyClass, как если бы foo был определен в основной реализации, а не в категории. Вы даже можете вызвать [super foo] из MyClass для доступа к foo, определенному для NSView.

Ответ 2

Чтобы продолжить на обратный ответ:

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

Все, что вы могли бы сделать в обычном интерфейсе класса, который вы можете сделать в категории, и все, что вы не должны делать в обычном интерфейсе класса, вы не должны делать в категории.

Итак:

Методы категорий не должны переопределять существующие методы (класс или экземпляр)

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

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

Две различные категории, реализующие тот же метод приводит к undefinedПоведение

Это нужно переписать, чтобы сказать: "Две разные категории, реализующие один и тот же метод для одного и того же класса, приводят к поведению undefined". Опять же, поскольку все методы для любого одного класса попадают в один и тот же файл, имея два метода в одном классе, очевидно, вызовет странность.

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

Если вы когда-либо путались о том, приведет ли категория к проблеме, просто спросите себя: "Будут ли методы в категории работать, если я скопировал и вложил их все в файлы".h/.m "класса?" Если ответ "да", значит, вы поняли. Если "нет", тогда у вас проблемы.