クラスChildはParentを拡張します。親は、を含むオプションのメソッドを持つプロトコルCを実装します-(void)d
。子には-d
;の実装があります。呼び出す必要があり[super d]
ますか?
言い換えれば、[super d]
何かがそれに応答する場合にのみ呼び出すために、どのコードを書くのですか?親の実装を制御していないと仮定します。いつでも変更される可能性があります。
これが私が考えたすべての方法です。私は現在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];
NSObjectの-respondsToSelectorの実装は、Childで実装を検出し、すべての場合にYESを返すため、これは機能しません。
どうやら賢明な答え3:
if ([[self superclass] instancesRespondToSelector:_cmd])
[super d];
これは、スーパークラスが常に-dを実装していることを知っている場合にのみ機能します。インスタンスがこのメソッドが存在するかどうかを動的に判断する場合、この手法は機能しません。実行時にParentの実装に対する静的な変更を取得するという点で1よりも優れています。
どうやら賢明な答え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またはランタイムリリースで変更される可能性があるため、このメカニズムは脆弱です。