как заблокировать вызов метода суперкласса в подкласс

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

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

Как лучше всего это сделать?

ОБНОВИТЬ ---

Так это то, что я пошел для. Я не отвечаю сам себе, так как в ответе Боаза упоминается несколько действительных способов сделать это, это именно то, что мне подходит. В подклассе я переопределяю метод следующим образом:

- (int)dangerousMethod
{
  [NSException raise:@"Danger!" format:@"Do not call send this method directly to this subclass"];
  return nil;
}

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


person Community    schedule 27.11.2008    source источник


Ответы (5)


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

Для команды С++ здесь: Objective C не позволяет вам помечать методы как частные. Вы можете использовать его систему категорий, чтобы разделить интерфейс на отдельные файлы (чтобы скрыть «частные» файлы), но все методы класса являются общедоступными.

person Boaz Stuller    schedule 27.11.2008
comment
Я не уверен, что это сработает. Если вы сделали то, что вы сказали, а затем вызвали какую-то безопасную функцию, расположенную в суперклассе, из подкласса, который, в свою очередь, вызвал небезопасную функцию, то метод ничего не делать/исключение в подклассе будет вызван из-за полиморфизм. - person Kibbee; 27.11.2008
comment
Звучит правильно для меня. Как вы сказали, пока я никогда не вызываю небезопасный метод суперкласса из суперкласса. Это несовершенное решение для далеко не идеальной практики, но, возможно, это лучшее, что я могу получить. - person Steph Thirion; 27.11.2008

Вы можете переопределить любые методы, которые хотите заблокировать, в файле .h вашего подкласса. Вы можете сделать dangerousMethod недоступным, поместив следующее в файл .h.

- (int)dangerousMethod __attribute__((unavailable("message")));

Это сделает метод dangerousMethod недоступным для всех, кто использует ваш подкласс.

Чтобы другой код не использовал версию суперкласса этого метода, вы можете дополнительно ограничить его, поместив его в свой файл .m.

- (int)dangerousMethod 
{
    return nil;     
}
person Community    schedule 01.06.2013
comment
Я не знал о __attribute__(()), спасибо! __attribute__((недоступно(сообщение))) у меня не сработало (я получил ошибку: указано неверное количество аргументов для атрибута «недоступно»), но __attribute__((недоступно)) сработало. - person Steph Thirion; 07.06.2013
comment
Вы можете использовать __unavailable вместо __attribute__((unavailable("message"))) - person cbh2000; 15.01.2014
comment
__unavailable (или от руки) не работают с унаследованными методами. Я пытался, и результаты печальны. Это выглядит как самый разумный способ справиться с этим, но на данный момент он не работает. - person sobri; 31.08.2014

примечание: я новичок в ObjC/Cocoa:

@implementation MyClass
-(void)myMethod:(NSString *)txt{
    if([self class] != [MyClass class]) return;
    NSLog(@"Hello");
}
@end

Питер

person Community    schedule 27.11.2008
comment
эй, Питер, это сработает, но... что, если у меня есть другой подкласс, которому нужен этот метод? - person Steph Thirion; 27.11.2008

В этой статье объясняется, как создавать закрытые переменные в Objective C. Они не совсем частные, но из того, что я читал, компилятор выдаст предупреждение, если вы попытаетесь вызвать их из подкласса.

person Kibbee    schedule 27.11.2008
comment
Эй, Кибби, я знаю эту процедуру. Как вы сказали, это не делает их частными. Выдает только предупреждения. Означает, что вы по-прежнему можете компилировать код с вызовами этих методов. И просто для корректности, в objc переменные могут быть приватными, а методы - нет. - person Steph Thirion; 27.11.2008

Если вы создаете методы в своем суперклассе как «частные», то у подкласса нет возможности их вызывать. Я не знаком с Objective C, но любой другой объектно-ориентированный язык, который я видел, имеет квалификатор "private".

person Kibbee    schedule 27.11.2008
comment
Забыл упомянуть, мне нужно, чтобы этот метод был общедоступным в суперклассе. Я отредактирую. - person Steph Thirion; 27.11.2008
comment
Почему он должен быть общедоступным в суперклассе? Если это метод обратного вызова, создайте класс адаптера для получения обратного вызова и скройте адаптер как частный объект. - person Mr Fooz; 27.11.2008
comment
Извините, на самом деле в objc нет общедоступных/приватных методов. Концепция адаптера интересная, я никогда о ней не слышал. Но лично я не хочу усложнять это еще больше, я бы предпочел создать исключение. - person Steph Thirion; 27.11.2008
comment
Мне нравится, когда меня модифицируют за ответ, который раньше был правильным, пока постер не изменил вопрос. - person Kibbee; 27.11.2008
comment
Кибби, мне жаль, что я плохо задал вопрос, и я изо всех сил старался исправить это, отредактировав, но я думаю, что это здесь неуместно, так как это не имеет ничего общего с вашей отрицательной оценкой. Это всегда было про objc, а objc не имеет приватных методов. - person Steph Thirion; 27.11.2008