Как узнать, вызывать ли метод суперкласса в Objective C

Class 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

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

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

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

Это не работает, потому что реализация NSObject -respondsToSelector найдет реализацию в 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 или среде выполнения.

6
задан outis 23 November 2011 в 13:55
поделиться