Переопределение методов с использованием категорий в Objective-C

Можно ли использовать класс для переопределения метода, который уже реализован с использованием категории? Вот так:

1) Исходный метод

-(BOOL) method {
  return true;
}

2) Переопределенный метод

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

Будет ли это работать, или это незаконно?

Ответ 1

Из документации Apple:

Хотя язык Objective-C в настоящее время позволяет вам использовать категорию для переопределения методов, которые наследует класс, или даже методов, объявленных в интерфейсе класса, вам настоятельно не рекомендуется делать это. Категория не является заменой для подкласса. Есть несколько существенных недостатков использования категории для переопределения методов:

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

  • Категория не может надежно переопределить методы, объявленные в другой категории того же класса.

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

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

Ответ 2

Вы можете сделать это, адаптировав Class Cluster или используя методы swizzling.

В противном случае поведение двух или более категоризированных методов undefined

Ответ 3

Старая документальная ссылка мертва; Лучшая замена, которую я мог найти, был здесь: Apple Docs:

Избегать разбора имени метода метода

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

Если имя метода, объявленного в категории, такое же, как метод в исходном классе, или метод в другой категории в том же классе (или даже в суперклассе), поведение undefined, в отношении которого метод используется во время выполнения. Это вряд ли будет проблемой, если вы используете категории с вашими собственными классами, но можете создавать проблемы при использовании категорий для добавления методов в стандартные классы Cocoa или Cocoa Touch.

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

Ответ 4

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

Из этого урока http://rypress.com/tutorials/objective-c/categories