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或运行时版本中更改。
答案 0 :(得分:5)
这些都不是必需的。
如果您是某个类或其他类的子类,则您需要知道是否要替换或补充行为。
换句话说,如果实现存在并且您希望以不同方式完成,则不要调用super。
如果实施不存在,则不要调用super。
如果 的实现存在,但您想要补充它,则称为super。
<强>附录:强>
执行情况随时可能发生变化与您的问题无关;重要的是接口是否会发生变化。
如果接口不断变化,那么这个类很难用于子类化,甚至是使用。
答案 1 :(得分:1)
不幸的是,我不知道这些答案是否合适。不幸的是,这归结为目的 - 它甚至可能不是你打算调用超类方法,有时候重写一个方法是替换方法,而不是在超类的功能之上链接你的功能。
归结为阅读文档并选择正确的方法。
如果这是关于您正在实施并希望使用一致方法的框架,那么2或3应该没问题。 1和4依赖于例外 - 除了objective-c中的真正特殊问题之外,它们并不真正用于任何事情。
答案 2 :(得分:-1)
在目标c中,您可以在协议中定义需要或可选的方法,但是您永远不能确定符合协议的类是否实际实现了该协议。
因此,您必须检查实例是否响应协议 我会选择选项2,这是最优雅的。 如果将来使协议方法可选,这仍然是正确的解决方案。
选项4我个人觉得很多Java-ish。