In Kotlin wird das Schlüsselwort super verwendet, um auf die Implementierung einer Methode oder Eigenschaft der Superklasse oder einer implementierten Schnittstelle zuzugreifen. Im Gegensatz zu Java erlaubt Kotlin, ausdrücklich anzugeben, über welche Schnittstelle oder Klasse die Implementierung der Methode aufgerufen werden soll, was besonders wichtig ist, wenn mehrere Schnittstellen mit identischen Methoden "konfligieren".
Besonderheit: Wenn eine Klasse mehrere Schnittstellen implementiert, in denen eine Methode mit der gleichen Signatur definiert und eine Standardimplementierung vorhanden ist, muss ausdrücklich angegeben werden, welche Implementierung verwendet werden soll.
Beispiel:
interface A { fun foo() = println("A") } interface B { fun foo() = println("B") } class C : A, B { override fun foo() { super<A>.foo() // Explicitly call A.foo super<B>.foo() // Explicitly call B.foo } }
Dies wird in Java nicht direkt unterstützt (Java erlaubt es Schnittstellen nicht, Felder/Methodeimplementierungen bis Java 8 zu haben, und sogar in Java 8 sind die Mechanismen anders).
"Kann man in Kotlin über mehrere Vererbungsebenen auf die Implementierung einer Methode der Superklasse zugreifen?"
super<Intermediate>.foo(), aber das ist nicht der Fall — man kann nur auf die unmittelbare Superklasse oder Schnittstelle zugreifen, die diese Methode direkt implementiert.Beispiel:
open class Base { open fun foo() = println("Base") } open class Mid : Base() { override fun foo() { println("Mid"); super.foo() } } class Child: Mid() { override fun foo() { super.foo() // calls Mid.foo() // super<Base>.foo() — Compilation error } }
Geschichte
In einem großen Projekt definierten die Schnittstellen
LoggerundAuditorbeide die Methoderecord(). Bei der Implementierung einer Klasse, die beide Schnittstellen erbt, hat der Programmiererrecord()nicht ausdrücklich überschrieben, was zu einem Kompilierungsfehler "Class must override public open fun record()" führte. Es musste die Methode manuell implementiert und ausdrücklich an die entsprechende Schnittstelle delegiert werden.
Geschichte
Bei dem Versuch, die implementierte Methode der Superklasse über mehrere Zwischenebenen hindurch aufzurufen (z. B.
super<Base>.foo()), trat ein Kompilierungsfehler auf. Der Entwickler kannte die Einschränkungen von Kotlin nicht und konnte nicht verstehen, warum der direkte Aufruf unmöglich war.
Geschichte
Nach einem API-Update hat eine der Schnittstellen eine Standardimplementierung der Funktion hinzugefügt, die mit einer anderen Schnittstelle übereinstimmte. Der alte Code ließ sich aufgrund von Implementierungskonflikten nicht mehr kompilieren — es musste ausdrücklich ein Konflikt gelöst werden, indem die Methode selbst implementiert und entschieden wurde, welche Implementierungen der Superinterfaces innerhalb von sich aufgerufen werden sollten.