Как вы знаете, вызывать ли метод суперкласса в Objective C - PullRequest
6 голосов
/ 23 ноября 2011

Класс Child расширяет Parent.Родитель реализует протокол C, который имеет необязательные методы, включая -(void)d.Ребенок имеет реализацию -d;должен ли он вызывать [super d]?

Другими словами, какой код я пишу для вызова [super d] тогда и только тогда, когда на него что-то ответит?Предположим, что я не контролирую реализацию Parent;это может измениться в любое время.

Вот все способы, о которых я думал.В настоящее время я использую номер 4.

Очевидно разумный ответ 1:

[super d]; // Delete this line if a runtime exception occurs when you try it

Это не работает, потому что родитель может реализовать -d динамически, так что это работает, когда вы тестируетеэто и не в поле.Или реализация Parent может измениться, так что результат этого теста больше не будет правильным.

Видимо разумный ответ 2:

if ([super respondsToSelector:_cmd])
    [super d];

Это не работает,потому что реализация -respondsToSelector в NSObject найдет реализацию в Child и вернет YES во всех случаях.

Видимо разумный ответ 3:

if ([[self superclass] instancesRespondToSelector:_cmd])
    [super d];

Это работает, если и толькоесли суперкласс знает, что он всегда реализует -d;если экземпляры динамически определяют, присутствует ли этот метод, этот метод не будет работать.Лучше, чем 1, поскольку он будет воспринимать статические изменения в реализации Parent во время выполнения.

Очевидно разумный ответ 4:

@try
{
    [super d];
}
@catch (NSException *exception)
{
    NSString *templateReason = [NSString stringWithFormat:
                                @"-[%@ %@]: unrecognized selector sent to instance %p"
                                ,NSStringFromClass([self superclass])
                                ,NSStringFromSelector(_cmd)
                                ,self];
    if (![exception.reason isEqualToString:templateReason])
        @throw exception;
}

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

Этот механизм хрупок, поскольку формат строки причины исключения в этом случае может быть изменен в будущем.SDK или выпуск времени выполнения.

Ответы [ 3 ]

5 голосов
/ 23 ноября 2011

Ничего из этого не нужно.

Если вы относитесь к тому или иному подклассу, вам уже нужно знать, заменяете ли вы или дополняете поведение.

Другими словами, если реализация существует и вы хотите, чтобы она выполнялась по-другому, вы не называете super.

Если реализация не существует, вы не называете super.

Если реализация действительно существует, но вы хотите дополнить ее, вы называете super.

Добавление:

Может ли реализация измениться в любое время, не имеет отношения к вашему вопросу; что важно, если интерфейс изменится.

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

1 голос
/ 23 ноября 2011

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

Это приходитвплоть до прочтения документации и выбора правильного подхода.

Если речь идет о платформе, которую вы внедряете и хотите использовать последовательный подход, то 2 или 3 должны подойти.1 и 4 основаны на исключениях, которые на самом деле не предназначены для использования ни для чего, кроме действительно исключительных проблем в target-c.

0 голосов
/ 23 ноября 2011

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

Таким образом, вы всегда должны проверять, отвечает ли экземпляр на протокол.
Я бы выбрал вариант 2, это самый элегантный вариант. Если в будущем вы сделаете метод протокола необязательным, это все равно будет правильным решением.

Вариант 4 Я лично нахожу много Java-иша.

...