Заміна методів із використанням категорій у Objective-C


87

Чи можу я використовувати категорію класу, щоб замінити метод, який вже реалізований за допомогою категорії? Подобається це:

1) Оригінальний метод

-(BOOL) method {
  return true;
}

2) Замінений метод

-(BOOL) method {
  NSLog(@"error?"); 
  return true; 
}

Це спрацює, чи це незаконно?

Відповіді:


146

З документації Apple :

Хоча мова Objective-C в даний час дозволяє використовувати категорію для заміни методів, які успадковує клас, або навіть методів, оголошених в інтерфейсі класу, ви від цього категорично не рекомендуєтесь . Категорія не є заміною підкласу. Існує кілька суттєвих недоліків використання категорії для заміни методів:

  • Коли категорія замінює успадкований метод, метод у категорії може, як зазвичай, викликати успадковану реалізацію за допомогою повідомлення до super. Однак, якщо категорія замінює метод, який існує в класі категорії, немає можливості викликати початкову реалізацію .

  • Категорія не може надійно замінити методи, заявлені в іншій категорії того ж класу.

    Це питання має особливе значення, оскільки багато класів какао реалізуються за допомогою категорій. Метод, визначений фреймворком, який ви намагаєтесь перевизначити, може бути реалізований у категорії, і тому, яка реалізація має пріоритет, не визначено.

  • Сама наявність деяких методів категорій може спричинити зміни поведінки у всіх рамках. Наприклад, якщо ви перевизначаєте windowWillClose:метод делегування в категорії на NSObject, усі представники вікна у вашій програмі реагують, використовуючи метод категорії; поведінка всіх ваших екземплярів NSWindow може змінитися. Категорії, які ви додаєте до класу фреймворку, можуть спричинити таємничі зміни в поведінці та призвести до збоїв.


Дякую, але я це вже знаю. Мені просто цікаво, чи моя справа є законною чи ні. Мій випадок трохи відрізняється від документів. :)
retix

Чому це інакше? Доктор каже, що це законно, ЯКЩО оригінальний метод не входить до категорії, але категорично не рекомендується. Тоді ви можете це зробити ...
Бенуа,

1
Дякую за пораду. Я бідний на цій мові. Я отримав від вас нову інформацію.
retix

1
Чи правильно перевизначити метод категорії, оголошений та реалізований у категорії суперкласу?
BergP

2
Посилання порушено, це нова версія? developer.apple.com/library/ios/documentation/Cocoa/Conceptual/…
RndmTsk 03.03.15


9

Старе посилання на документацію мертве; найкраща заміна, яку я міг знайти, була тут: Документи Apple :

Уникайте зіткнень назв методів категорій

Оскільки методи, оголошені в категорії, додаються до існуючого класу, потрібно бути дуже обережним щодо назв методів.

Якщо ім'я методу, оголошеного в категорії, збігається з методом у вихідному класі або методом в іншій категорії того ж класу (або навіть суперкласу), поведінка невизначена щодо того, який метод реалізації використовується на час виконання. Це менш імовірно, що це проблема, якщо ви використовуєте категорії з власними класами, але може спричинити проблеми при використанні категорій для додавання методів до стандартних класів какао або какао Touch.

Це Apple, використовуючи легший дотик, але головне те саме: ви запрошуєте катастрофу, тому що непередбачувана поведінка мовчить.


2

Важливо зазначити, що категорія також може бути використана для заміни існуючих методів у базовому класі (наприклад, метод приводу класу Car), але ніколи цього робити не слід. Проблема в тому, що категорії - це плоска організаційна структура. Якщо ви перевизначите існуючий метод у Car + Maintenance.m, а потім вирішите, що хочете знову змінити його поведінку іншою категорією, Objective-C не зможе дізнатися, яку реалізацію використовувати. Підклас майже завжди є кращим варіантом у такій ситуації.

З цього підручника http://rypress.com/tutorials/objective-c/categories

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.