Geschichte der Frage:
Die Überschreibung von Methoden ist die Grundlage der OOP, doch in Java war override ursprünglich nicht verpflichtend. Kotlin ist eine streng typisierte Sprache, die die verpflichtende Verwendung von override eingeführt hat, um die Klarheit des Codes zu erhöhen und zufällige Fehler bei der Vererbung zu vermeiden.
Problem:
Ohne ausdrückliches Override ist es leicht, bei der Beschreibung eines Interfaces/Klasse einen Fehler zu machen: Tippfehler im Namen, Typ, Modifikator. Das Programm stürzt nicht ab, aber die erwartete Überschreibung funktioniert nicht. Kotlin löst dieses Problem radikal.
Lösung:
In Kotlin muss eine Methode, die überschrieben werden soll, als open (oder abstract/interface) deklariert werden. Für die Überschreibung ist es zwingend erforderlich, override zu schreiben. Stimmen die Signaturen nicht überein, gibt es einen Compilerfehler. Dies verhindert die meisten klassischen Bugs in Java.
Beispielcode:
open class Base { open fun greet() { println("Hello!") } } class Child : Base() { override fun greet() { println("Hi!") } }
Schlüsselmerkmale:
Kann man versehentlich eine Funktion überschreiben, wenn man override vergisst?
Nein. Wenn Sie override ausgelassen haben, wird die deklarierte Methode als neue Methode der Klasse betrachtet, und es findet keine Überschreibung statt — der Compiler gibt einen Fehler aus, wenn open bei der Basis-Methode vorhanden ist.
Beispielcode:
open class A { open fun test() {} } class B : A() { fun test() {} // überschreibt nicht! Analog zu test2() }
Dürfen eigene Methoden eine strengere Sichtbarkeit als die des Elternelements haben?
Nein. Die Sichtbarkeit der überschriebenen Methode darf nicht eingeschränkt werden. Wenn die Basis-Methode öffentlich ist, kann das override nicht privat/protected/internal sein. Der Compiler gibt einen Fehler aus.
Kann eine override-Komponente final sein?
Ja! Wenn Sie eine weitere Überschreibung nicht wünschen, fügen Sie final hinzu:
class D : Base() { final override fun greet() { //... } }
In Java:
public class Parent {void foo(){} } public class Child extends Parent {void foo(int x){} }
Eine Überschreibung wird erwartet, aber in Wirklichkeit ist es eine Überladung. Die Aufrufe gehen nicht in die richtige Methode.
Vorteile:
Nachteile:
In Kotlin:
open class Parent { open fun foo() {} } class Child : Parent() { override fun foo() { /*...*/ } }
Vorteile:
Nachteile: