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 или среде выполнения.