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

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

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

-(BOOL) method {
  return true;
}

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

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

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

4 ответа

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

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

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

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

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

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

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

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

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

Избегайте столкновений имен методов категорий

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

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

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

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

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

Другие вопросы по тегам