默认情况下您调用super,除非您知道您没有破坏该功能。
我创建了一个gist。您可以将其复制到您自己的游乐场并玩弄它。但答案是:
我对你有这种困惑。您基本上是在问扩展行为与覆盖行为有什么区别。
Swift 不能很好地告诉你他们的不同之处。
他们的共同点是都需要用override 标记函数,但有时你在超类的实现之外做一些事情(扩展),有时你只是完全重写它(覆盖)
假设我们有以下类:
class Person {
var age : Int?
func incrementAge() {
guard age != nil else {
age = 1
return
}
age! += 1
}
func eat() {
print("eat popcorn")
}
}
我们可以初始化它然后做:
var p1 = Person()
p1.incrementAge() // works fine
现在假设我们这样做了:
class Boy : Person{
override func incrementAge() {
age! += 2
}
}
var b1 = Boy()
b1.incrementAge()
你认为会发生什么?!
它会崩溃。因为在超类中,我们正在对age 进行nil 检查,但在我们的子类中我们从不调用super
要使其正常工作,我们必须致电super。
class GoodBoy : Person{
override func incrementAge() {
super.incrementAge()
age! += 2
}
}
var b2 = GoodBoy()
b2.incrementAge() // works fine.
我们可以不用直接打电话给super。
class AlternateGoodBoy : Person{
override func incrementAge() {
guard age != nil else {
age = 1
return
}
age! += 2
}
}
var b3 = AlternateGoodBoy()
b3.incrementAge() // works fine.
^^ 上述方法可行,但我们并不总是知道超类的实现。一个真实的例子是UIKit。我们不知道当viewDidLoad 被调用时会发生什么。因此我们必须调用super.viewDidLoad
话虽如此,有时我们不能打电话给super 并且完全没问题,因为我们知道 super 做什么,或者可能只是不关心并想要完全摆脱它。例如:
class Girl : Person{
override func eat() {
print("eat hotdog")
}
}
var g1 = Girl()
g1.eat() // doesn't crash, even though you overrode the behavior. It doesn't crash because the call to super ISN'T critical
然而,最常见的情况是您调用super,但还要在其上添加一些内容。
class Dad : Person {
var moneyInBank = 0
override func incrementAge() {
super.incrementAge()
addMoneyToRetirementFunds()
}
func addMoneyToRetirementFunds() {
moneyInBank += 2000
}
}
var d1 = Dad()
d1.incrementAge()
print(d1.moneyInBank) // 2000
专业提示:
与大多数先调用 super 然后调用其余部分的覆盖不同,对于 tearDown 函数,最好在函数末尾调用 super.tearDown()。通常,对于任何“删除”功能,您都希望在最后调用 super。例如viewWillDisAppear/viewDidDisappear