子类扩展父类。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 或运行时版本中更改。