Могут ли категории наследоваться?

Скажем, у меня есть класс Parent, а дочерними являются Child1 и Child2.

Я объявляю Parent+ParentCategory, а затем объявляю метод:

-(void) Redraw;

Позже я хочу, чтобы функция Redraw Child1 отличалась от функции Redraw Child2.

Могу ли я объявить Child1+Child1Category, а затем переопределить

-(void) Redraw

Может ли -(void)Redraw из Child1 вызывать функцию в родительской категории?

Это можно сделать?

Какой подход был бы хорошим?

Я знаю, что классы могут наследовать друг друга. Я знаю, что протокол может расширять друг друга. Интересно, почему категории нет?


person user4951    schedule 07.06.2013    source источник
comment
Ранее был задан аналогичный вопрос category-on-the-sup" title="могу ли я использовать категорию для переопределения метода, который сам находится в категории на sup">stackoverflow.com/questions/3357282/ . Но это не отвечает на ваш вопрос о функции категории child1, вызывающей родительскую категорию.   -  person Adithya    schedule 07.06.2013


Ответы (3)


Я не согласен с данными ответами:

О.: Неправда, что методы категории побеждают методы класса. Это деталь реализации, но поведение не определено.

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

Б. Но это не имеет значения. Вы не определяете метод в категории, которая определена в классе, и не определяете метод в двух конфликтующих категориях. Цит. просто не относится к вашему случаю. Это относится к чему-то вроде этого:

@interface A : NSObject
- (void)doSomething;
@end
@implementation A
- (void)doSomething {}
@end

@interface A (Addition)
- (void)doSomething;
@end
@implementation A (Addition)
- (void)doSomething {}
@end

Если я правильно понял, вы не хотите этого делать. Вы хотите что-то вроде этого:

Базовый уровень:

@interface A : NSObject
@end
@implementation A
@end

@interface A (Addition)
- (void)doSomething;
@end
@implementation A (Addition)
- (void)doSomething {}
@end

Это не нарушает правило, потому что в категории нет метода, который есть в классе.

Уровень подкласса:

@interface B : A
@end
@implementation B
@end

@interface B (Addition)
- (void)doSomething;
@end
@implementation B (Addition)
- (void)doSomething {}
@end
  1. На уровне Б нет конфликта по той же причине, по которой нет конфликта на уровне А.

  2. Кто-то может сказать, что существует конфликт, потому что B наследует -doSomething от A. Но это не конфликт, потому что в этом случае применяется правило приоритета: подклассы перезаписывают методы.

Вы можете сделать это.

Редактировать:

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

person Amin Negm-Awad    schedule 07.06.2013
comment
Просто вопрос, сэр: вы пробовали то, что объясняете выше? Я пишу некоторые тесты прямо сейчас (может быть, 2:00 не самый подходящий момент для написания кода, но мне было просто любопытно), и код даже не компилируется, жалуясь на повторяющийся символ. - person Antonio E.; 08.06.2013
comment
Синьор, я несколько раз реализовывал эту систему для предикатов. И я скомпилировал код выше. Если у вас есть ошибка повторяющегося символа, вы должны сделать следующее: 1. Проверьте свою копию и вставку. Вы сделали ошибку, скопировав и вставив код. 2. Сообщите, где вы получили повторяющийся символ. Как опытный программист Objective-C, вы знаете, что классы и категории открывают отдельное пространство имен, поэтому получить дублирующийся символ для разных классов и категорий очень сложно. Вот пример проекта: cocoading.de/webspace/CategoriesAndClasses.zip - person Amin Negm-Awad; 08.06.2013
comment
Я должен уточнить: С цит. Я имел в виду цит в вашем ответе. Документация цит. в моем ответе не совсем правильно, потому что метод в суперклассе не может конфликтовать с методом в подклассе. - person Amin Negm-Awad; 08.06.2013
comment
Вернулись с загара. (НАКОНЕЦ-ТО ЛЕТО!) :) Хочу добавить кое-что, но думаю, что почти во всех случаях оно выполнено. Все пакеты, которые добавляют такую ​​категорию в подкласс, должны быть загружены. - person Amin Negm-Awad; 08.06.2013

Буду переигрывать с цит. из этого ответа:

Скажем так. Не переопределяйте методы, используя категории, точку, когда-либо, конец ответа.

Причина этого в том, что, хотя точно известно, что метод категории всегда выигрывает у метода класса (то есть, если вы реализуете метод в категории, которая уже объявлена ​​в классе, вы расширяете с категорией метод категории будет вызываться.) когда у вас есть несколько категорий, реализующих один и тот же метод, реализация которого имеет приоритет, не определена

person Antonio E.    schedule 07.06.2013
comment
Пожалуйста, посмотрите на мой ответ. - person Amin Negm-Awad; 08.06.2013

Неразумно использовать категорию для этого. Категории добавляют методы к текущему классу. Если существует несколько методов с одинаковым именем, он заменит старый (это НЕ переопределение). Но, к сожалению, трудно сказать, какой из них заменен. Не делайте этого, иначе у вас могут быть проблемы.

И вы, вероятно, не можете вызвать метод в Parent из дочерней категории. Самая правильная конструкция здесь — это протокол.

person onevcat    schedule 07.06.2013
comment
Ни в коем случае не существует метода в категории, который также определен в классе категории. - person Amin Negm-Awad; 08.06.2013