在 Swift 中,override 是一个关键字,用于在子类中重写父类的功能。它是面向对象编程中“继承”机制的核心组成部分之一。
作用
当子类需要重新定义父类的方法、计算属性、下标或初始化器的实现时,必须使用 override 关键字,Swift 编译器可以确保:
1、父类确实有这个可以被重写的成员;
2、没有拼错名字或参数;
3、避免不小心定义了一个全新的方法(而不是重写)。
重写类型
Override可以重写普通方法、计算数学、下标、required 或 convenience 或 designated 构造器,并且需要符合规则。
class Animal {
var name: String {
return "Animal"
}
}
class Dog: Animal {
override var name: String {
return "Dog"
}
}
上面这种是合法的,因为是通过 override 来重写父类的计算属性。这种方式是 Swift 支持的“受控的 shadow”。
需要注意的是,存储属性不允许shadow,因此无法使用override。
存储属性为什么不能重写?
class Animal {
var name: String = "Animal"
}
class Dog: Animal {
override var name: String = "Dog" // ❌ 报错:Cannot override stored property
}
原因是:
父类的存储属性有一块内存;
Swift 不允许子类再重复分配这块内存,会破坏对象内存结构;
只能通过重写计算属性等类型来“覆盖”行为,而不是实际重写内存存储。
重新方法报错
如果需要重写父类的方法,没有添加override关键字,还会报错:
class Animal {
func getName() {
print("name:\(name)")
}
}
class Dog: Animal {
func getName() { // 报错,覆盖声明需要“override”关键字
print("name:\(name)")
}
}
报错内容:
Overriding declaration requires an 'override' keyword
这表示在重写方法等类型时,需要使用override关键字。
为什么Swift会严格要求重写使用override关键字?
这是因为,防止无意中写错函数名,例如想要重写speak方法:
class Animal {
func speak() {
print("Animal speaks")
}
}
class Dog: Animal {
func speek() { // 👈 拼错了,少写了一个 "a"
print("Dog barks")
}
}
想要重写speak(),但实际上写了一个新方法,Animal.speak() 依然会被调用,程序行为与预期不一致,而且不容易发现错误。
因此,Swift会要求在重写的方法上显式加上override:
override func speak() {
...
}
如果在重写的过程中拼错,编译器会立即报错:
Method does not override any method from its superclass
表示方法不会覆盖其父类中的任何方法。
这样做的好处:
1、编译器能自动发现潜在 bug;
2、明确在继承体系中重写方法;
3、提高代码的可读性和可维护性。
总结
在Swift知识点的文章《从错误到解决:Swift required构造函数逐步解析》中,有提及override的使用,因此,如果完全不理解父类、子类以及override使用场景,可以到前文中进一步了解。
override 是在子类中重写父类行为的唯一合法方式。
Swift 要求显式写出 override,防止误操作。
常见用于:方法、计算属性、下标、构造器(有条件)。
相关文章
从错误到解决:Swift required构造函数逐步解析:https://fangjunyu.com/2024/10/13/%e4%bb%8e%e9%94%99%e8%af%af%e5%88%b0%e8%a7%a3%e5%86%b3%ef%bc%9aswift-required%e6%9e%84%e9%80%a0%e5%87%bd%e6%95%b0%e9%80%90%e6%ad%a5%e8%a7%a3%e6%9e%90/