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

Мне известны несколько правил, касающихся категорий Objective-C:

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

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

@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 имеет приоритет,но я не уверен, что это гарантированно произойдет, или просто один конкретный вариант неопределенного поведения.

Ответы [ 2 ]

33 голосов
/ 11 июля 2010

Продлить на оттянутый ответ:

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

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

Итак:

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

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

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

Реализация двух разных категорий тот же метод приводит к неопределенным поведение

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

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

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

12 голосов
/ 11 июля 2010

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

...