Swift引用父类的super
Swift引用父类的super

Swift引用父类的super

super 是 Swift(和 Objective-C)中的一个关键字,用来引用父类(超类)中的实现。可以把它理解为“调用父类版本的方法、属性或构造器”的方式。

当子类中重写(override)了一个方法,但仍然希望保留父类的一部分行为,就可以通过 super 来调用父类原来的实现。

常见用法

1、调用父类的方法

class Animal {
    func makeSound() {
        print("Some generic animal sound")
    }
}

class Dog: Animal {
    override func makeSound() {
        super.makeSound()  // 调用父类方法
        print("Woof!")
    }
}

2、访问父类的属性

class Person {
    var name: String = "Unknown"
}

class Student: Person {
    override init() {
        super.init()
        print("Student name is \(super.name)") // 访问父类属性
    }
}

为什么需要调用super?

在子类中使用override某个方法时,是在改变或扩展父类的行为,调用super就是把父类原本的逻辑也执行一遍。

例如,调用super的叫声:

class Dog: Animal {
    override func speak() {
        super.speak() // 调用父类的 speak 方法
        print("Dog barks")
    }
}

如果不调用super.speak(),那么父类中的UI初始化逻辑(可能包括设置默认状态、约束、事件监听)不会执行,可能导致界面不完整或功能失效。

就像狼本身是通过喉咙发声,如果狼狗不继承狼的叫声(不使用喉咙),那么狼狗可能会嘴巴发出咩咩的叫声,那么这个狼狗就不正常了。

不调用super是否可行?

语法上可以,Swift运行不调用super,编译器不会强制要求,除了构造器的super.init()。

class Animal {
    func speak() {
        print("Woo~")
    }
}
class Dog: Animal {
    override func speak() { // 无报错
        print("Dog barks")
    }
}

如果不调用super就意味着完全替换父类的逻辑。

例如在实际应用中,NSView类不调用super:

class CustomView: NSView {
    override func draw(_ dirtyRect: NSRect) {
        // 忘了调用 super.draw(dirtyRect)
        // ...自定义绘图代码
    }
}

如果不调用 super.draw(…),系统可能不会清空背景、绘制默认内容,导致图层残影、重绘出错。

因此,推荐默认调用super,这样可以保留父类功能逻辑,然后再添加额外的逻辑。

如果父类方法为空,或者父类逻辑与子类的逻辑存在冲突,那么就可以不调用super,而是完全重写子类。

例如:

class Animal {
    func makeSound() {
        print("Some sound")
    }
}

class Cat: Animal {
    override func makeSound() {
        print("Meow") // 不需要 super,因为完全重写
    }
}

在UIKit / AppKit等场景中,例如 viewDidLoad()、draw(_:)等方法,都需要调用super,完成父类初始化,确保行为一致性与稳定性。

必须调用的super.init()

因为子类不是孤立的,必须构建好继承的部分。

一个子类对象由两部分组成:

子类实例 = 父类部分 + 子类部分

构造器的责任是完成整个对象内存结构的初始化,Swift强制要求:

子类必须调用 super.init(),以确保 父类的属性和内部状态被正确初始化。

这是 Swift 安全性设计的一部分,叫做两阶段初始化机制(Two-Phase Initialization)。

例如:

class Animal {
    var name: String
    init(name: String) {
        self.name = name
        print("Animal 被初始化")
    }
}

class Dog: Animal {
    var breed: String
    init(name: String, breed: String) {
        self.breed = breed
        // 这里必须调用 super.init
        super.init(name: name)
        print("Dog 被初始化")
    }
}

如果注释掉super.init(),就会报错:

'super.init' isn't called on all paths before returning from initializer

表示初始化程序返回之前,并没有调用super.init()。

不调用super.init()是否可行?

不可以,除非:

父类是 Swift 的 struct 或 enum(这些没有继承,不存在 super);

或者使用的是 Swift 提供的“默认初始化器”且没有自定义构造器(很少见);

或者子类本身是最终类(final class)并显式不使用继承(仍需构造器初始化所有属性)。

调用super.init()的实际意义

真实作用:

1、初始化父类的所有属性;

2、调用父类的初始化逻辑(包括设置状态、观察者、资源等);

3、让整个对象在内存中是合法的、完整的。

举个例子,例如接力比赛,你在第四条道上,你需要完成接力跑,但是你必须确认接力棒在你手上,而不是直接跑步。

必须要确认:

1、拿到了接力棒(父类的init()),这也意味着前面的任务已经完成;

2、完成自己的接力跑(子类的属性);

3、如果没有拿到接力棒,直接跑步,那么比赛就会结束(对象非法、未初始化)。

自动调用的例外情况

在Swift中,编译器默认自动调用super.init(),例如:

class A {
    init() { print("A") }
}

class B: A {
    // 不定义 init,编译器自动生成 init,并且插入 super.init()
}

如果子类定义了自定义构造期init(),那么就必须手动调用super.init()。

注意事项

super 只能在类中使用,结构体和枚举不支持继承,因此不能使用。

super 只能用于子类中,且前提是该方法、属性或构造器在父类中存在。

在 override 的方法中调用 super 是可选的,但在某些框架中(如 UIKit),必须调用 super(如 viewDidLoad())。

实际用例

例如,存在一个父类Animal类:

class Animal {
    func speak() {
        print("Animal makes a sound")
    }
}

子类Dog,使用override和super:

class Dog: Animal {
    override func speak() {
        super.speak() // 调用父类的 speak 方法
        print("Dog barks")
    }
}

SwiftUI视图:

class Animal {
    func speak() {
        print("Animal makes a sound")
    }
}

class Dog: Animal {
    override func speak() {
        super.speak()
        print("Dog eat Dog")
    }
}

struct ContentView: View {
    let dog = Dog()
    init() {
        dog.speak()
    }
    var body: some View { }
}

控制台输出:

Animal makes a sound
Dog barks

总结

子类在继承父类时,默认自动调用父类的init()方法,如果子类需要自定义构造方法,那么必须显式调用super.init()。

构造器调用 super.init(…) 是强制要求,否则编译报错。

在方法重写时,不强制使用super,但是不使用super可能会忽略父类重要逻辑(如视图加载、事件响应等),除非明确完全替代父类行为,否则建议调用super以确保功能稳定。

总结,构造器必须调用super.init(),方法中根据情况调用super。

相关文章

Swift重写父类的override:https://fangjunyu.com/2025/05/18/swift%e9%87%8d%e5%86%99%e7%88%b6%e7%b1%bb%e7%9a%84override/

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注