【发布时间】:2011-11-23 13:51:11
【问题描述】:
子类扩展父类。 Parent 实现协议 C,该协议具有可选方法,包括 -(void)d。 Child 有一个-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 或运行时版本中更改。
【问题讨论】:
标签: objective-c super respondstoselector