In Kotlin kan een klasse één primary constructor en een onbeperkt aantal secondary constructors hebben. Het verschil met Java is dat de primary constructor in de header van de klasse wordt gedeclareerd en parameters en modifiers kan bevatten. Secondary constructors moeten altijd een andere secondary constructor, de primary constructor of de constructor van de superklasse aanroepen (met behulp van het sleutelwoord super).
Belangrijke kenmerken:
: super(...).super(...) of een andere secondary/primary constructor.Voorbeeld van gebruik met overerving:
open class A(val a: Int) { constructor(a: Int, str: String) : this(a) { println("Secondary in A: $str") } } class B : A { constructor(a: Int) : super(a) { println("Secondary in B") } constructor(a: Int, s: String) : super(a, s) { println("Secondary #2 in B") } }
Wat is het verschil met de benadering in Java:
Is het mogelijk om in Kotlin een afgeleide klasse te creëren zonder expliciet de constructor van de superklasse aan te roepen, als er alleen een bepaalde constructor in de basis klasse is?
Antwoord: Nee, in tegenstelling tot Java is de aanroep van de superconstructor in Kotlin verplicht en moet deze expliciet worden aangegeven, hetzij in "het hoofd" van de klasse, hetzij na het sleutelwoord : super().
Voorbeeld van een fout:
open class Base(val x: Int) class Derived : Base // Compilatiefout!
Verhaal
In een microservices project na de migratie naar Kotlin werd de expliciete verwijzing naar de ouderconstructor vergeten: de constructor van de superklasse met een verplichte parameter werd niet aangeroepen, de service compileerde niet, en het was nodig om de handtekeningen te refactoren.
Verhaal
Het Android-project had een diepe hiërarchie (Activity → BaseActivity → CustomActivity), het toevoegen van een secondary constructor verloor parameters, waardoor de verkeerde basisconstructor werd aangeroepen en delen van velden null bleven — de applicatie viel op runtime met NPE.
Verhaal
In open-source bibliotheekcode omzeilde de secondary constructor in de afgeleide klasse per ongeluk de primary constructor, wat leidde tot twee verschillende initialisatiepaden: soms werd het veld geïnitialiseerd, soms niet. De fout werd pas na veel tijd gevonden door complexe bugrapporten.