Переопределение методов с использованием категорий в Objective-C
Могу ли я использовать категорию класса для переопределения метода, который уже реализован с использованием категории? Как это:
1) Оригинальный метод
-(BOOL) method {
return true;
}
2) Переопределенный метод
-(BOOL) method {
NSLog(@"error?");
return true;
}
Будет ли это работать, или это незаконно?
4 ответа
Хотя язык 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