问题的历史:
重写方法是面向对象编程的基础,但在 Java 中,一开始并不强制要求使用 override。Kotlin 是一种严格类型语言,引入了强制使用 override,以提高代码的明确性并避免继承时的意外错误。
问题:
如果没有明确指定 override,在描述接口/类时容易出错:在名称、类型、修饰符上拼写错误。程序不会崩溃,但预期的重写不会生效。Kotlin 从根本上解决了这个问题。
解决方案:
在 Kotlin 中,为了使方法可以被重写,必须将其声明为 open(或 abstract/interface)。重写时必须显式使用 override。如果签名不匹配——则会产生编译错误。这防止了大多数 Java 的经典 bug。
代码示例:
open class Base { open fun greet() { println("Hello!") } } class Child : Base() { override fun greet() { println("Hi!") } }
关键特性:
如果忘记 override,是否可以偶然重写函数?
不可以。如果您遗漏了 override,声明的方法将被视为类的新方法,而不会发生重写——如果基本方法存在 open,编译器将产生错误。
代码示例:
open class A { open fun test() {} } class B : A() { fun test() {} // 不重写!与 test2() 类似 }
自己的方法是否可以比父类的有更严格的可见性?
不可以。不能缩小重写方法的可见性范围。例如,如果基本方法是 public,override 重写不能是 private/protected/internal。编译器将产生错误。
override 组件可以是 final 吗?
可以!如果不希望进一步重写,可以添加 final:
class D : Base() { final override fun greet() { //... } }
在 Java 中:
public class Parent {void foo(){} } public class Child extends Parent {void foo(int x){} }
期望重写,但实际上是重载。调用不会进入正确的方法。
优点:
缺点:
在 Kotlin 中:
open class Parent { open fun foo() {} } class Child : Parent() { override fun foo() { /*...*/ } }
优点:
缺点: