在覆盖iOS方法时何时使用super

13

我的同事有时在重写ios方法时会调用super,有时则不会。这似乎主要基于他们的经验。是否有一个指导方针来决定是否调用super?

// Has super
override func awakeFromNib() {
    super.awakeFromNib()
}

// No super
override func drawRect(rect: CGRect) {
}

3
@matt,你的评论对任何人都没有帮助,请提供文档或其他 Stack Overflow 帖子的引用。https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Inheritance.html#//apple_ref/doc/uid/TP40014097-CH17-ID196 - alexisSchreier
1
@alexisSchreier 我不同意你的观点。我已经非常直接、简明和正确地回答了问题。要知道在实现awakeFromNib时是否需要调用super,必须阅读有关awakeFromNib的文档等等。没有捷径可走。我的评论对所有人都有帮助。 - matt
2个回答

9

在是否调用给定方法的超级实现方面,实际上没有一条经验法则。这应该根据超类对该方法实现的文档建议和您的要求来具体确定。

为了解释为什么你提供的两个例子可能是这样的,我们可以查看{{link1:-[UIView drawRect:]}的文档,其中写道:

如果您直接子类化UIView,则您实现此方法不需要调用super。但是,如果您正在子类化其他视图类,则应在实现中的某个时刻调用super。

以及{{link2:-[NSObject awakeFromNib]}的文档,其中写道:

您必须调用awakeFromNib的超级实现,以便父类有机会执行他们所需的任何其他初始化。虽然此方法的默认实现不执行任何操作,但许多UIKit类提供非空实现。

大多数情况下,您应该调用方法的超级实现(请参见下面的注释),这可能是一个安全的做法。但要注意,有些方法需要您调用它们的超级实现,有些则不需要,还有一些甚至要求您在覆盖时在特定点调用超级实现。因此,请记住,如果有疑问,请务必查阅文档。


6
对于初学者,我的回答会略有不同:“始终调用超类实现”。如果编译器抱怨该方法未定义,请删除该调用。有时不需要调用super,因为基类的super实现什么也不做,但在不需要调用它时调用它比需要调用它时不调用更安全。 - Duncan C
3
@DuncanC:这是个好观点。通常情况下,当不确定时调用super可能是更安全的默认操作。尽管如此(我无法想到一个例子),但可能存在这样一种情况,即父类方法的super实现具有副作用,可以改变你的子类实现中也改变了的状态。在这种情况下,你重写中super调用的位置很重要,可能会导致进一步的混乱。 - Mick MacCallum
3
我认为常规做法是先调用超类版本,然后再添加你的自定义代码。这样,你对方法所做的任何更改都会在超级实现完成其任务之后应用。 - Duncan C
1
通常是这样的,但也有例外情况。比如说UIView updateConstraints文档明确指出:“在你的实现中,将调用[super updateConstraints]作为最后一步。” - Mick MacCallum
@i_am_jorf 指出,对于某些类/方法,您明确不应调用超级实现。因此,答案实际上需要是“您可能应该调用覆盖的方法的超级实现,但始终阅读文档。” - Duncan C
显示剩余3条评论

0
向super发送消息是一种调用继承链上方超类定义的方法实现的方式。最常见的使用情况是在覆盖方法时使用super。调用super将允许父类进行一些准备工作。如果您要覆盖方法,则必须调用super,否则可能会出现一些无效状态,因为超类实现可能已经错过了初始化某些状态。

1
如果你要覆盖一个方法,你必须调用super。但情况并非如此 - 这取决于特定的方法是否必须这样做。 - Gruntcakes
是的,例如UIViewController loadView明确表示:“您对此方法的自定义实现不应调用super。”我的建议是始终检查文档,并在不确定时默认调用super(如果文档没有说明)。 Android相对于iOS的一个好处是您可以查看源代码并查看super实际执行了什么。 :-/ - i_am_jorf
@i_am_jorf 我在那个文件链接中没有看到这个声明。 - Sebastian Dwornik
文档已经更改。现在在此处声明:[https://developer.apple.com/documentation/uikit/uiviewcontroller/1621454-loadview]。 - i_am_jorf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接