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/