In Kotlin wordt het keyword super gebruikt om naar de implementatie van een methode of eigenschap van de superklasse of de geïmplementeerde interface te verwijzen. In tegenstelling tot Java stelt Kotlin je in staat om expliciet aan te geven via welke interface of klasse je de methode-implementatie wilt aanroepen, wat vooral belangrijk is bij 'conflicten' van meerdere interfaces met dezelfde methoden.
Kenmerk: Als een klasse meerdere interfaces implementeert waarin een methode met dezelfde handtekening gedefinieerd is en er een standaardimplementatie is, dan moet je expliciet aangeven welke implementatie je wilt gebruiken.
Voorbeeld:
interface A { fun foo() = println("A") } interface B { fun foo() = println("B") } class C : A, B { override fun foo() { super<A>.foo() // Explicit aanroepen A.foo super<B>.foo() // Explicit aanroepen B.foo } }
Dit wordt in Java niet direct ondersteund (Java staat interfaces niet toe om velden/methode-implementaties te hebben tot Java 8, en zelfs in Java 8 — de mechanismen zijn anders).
"Is het mogelijk om in Kotlin naar de implementatie van een methode van de superklasse te verwijzen via meerdere niveaus van overerving?"
super<Intermediate>.foo(), maar dat is niet zo — je kunt alleen verwijzen naar de directe superklasse of interface,
waarvan die bepaalde methode direct is geïmplementeerd.Voorbeeld:
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() // roept Mid.foo() aan // super<Base>.foo() — compilatiefout } }
Verhaal
In een groot project definieerden de interfaces
LoggerenAuditorbeide de methoderecord(). Bij het implementeren van een klasse die beide interfaces erfde, had de programmeurrecord()niet expliciet geherdefinieerd, waardoor de compilatiefout "Klas moet de publieke open functie record() overschrijven" ontstond. De methode moest handmatig worden geïmplementeerd en expliciet aan de betreffende interface worden gedelegeerd.
Verhaal
Bij het proberen om de geïmplementeerde methode van de superklasse aan te roepen via meerdere tussenliggende lagen (bijv.
super<Base>.foo()), ontstond er een compilatiefout. De ontwikkelaar kende de beperkingen van Kotlin niet en begreep niet waarom de directe aanroep onmogelijk was.
Verhaal
Na een API-update had een van de interfaces een standaardfunctie-implementatie toegevoegd, die samenviel met een andere interface. Oude code compileerde niet meer vanwege het conflict van implementaties — men moest het conflict expliciet oplossen door de methode zelf te implementeren en te kiezen welke implementaties van superinterfaces binnen zichzelf moesten worden aangeroepen.