首页 > 解决方案 > 您是否需要从每个子类的函数中调用超类的实现

问题描述

例如,您定义了一个覆盖其超类中的函数 f 的子类。在覆盖内部,您是否需要调用超类的 f 函数。

标签: swiftfunctional-programmingsubclasssuperclass

解决方案


默认情况下,您调用super除非您知道您没有破坏该功能。


我创建了一个要点。您可以将其复制到您自己的游乐场并玩弄它。但答案是:

我对你有这种确切的困惑。您基本上是在问扩展行为与覆盖行为之间有什么区别。

斯威夫特并没有很好地告诉你他们的区别。他们的共同点是都需要用 来标记函数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()

你觉得会发生什么?!

它会崩溃。因为在超类中,我们正在nil检查age,但在我们的子类中我们从不调用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


推荐阅读