In Kotlin kan elke klasse één primary constructor (primaire) en meerdere secondary constructors (secundaire) hebben. Constructor delegation is een mechanisme waarbij een secondary constructor verplicht een primary constructor direct moet aanroepen, of een andere secondary constructor van dezelfde klasse (en uiteindelijk de primary). Als een klasse van een andere klasse erft, moet elke secondary constructor van de afgeleide klasse expliciet de aanroep naar de constructor van de superklasse delegeren, indien nodig.
In Java kunnen constructors elkaar direct aanroepen met behulp van this() of super(), door constructors in verschillende combinaties te overbelasten. In Kotlin is dit concept geformaliseerd: een klasse kan slechts één primary constructor hebben, secundaire constructors kunnen gebruik maken van delegatielogica die expliciet moet worden aangegeven.
Een onjuiste implementatie van delegatie kan leiden tot compilatiefouten: je kunt de primary constructor niet overslaan als deze is gedeclareerd, of de superconstructor niet aanroepen in de afgeleide klasse als de basisklasse geen standaardconstructor heeft. Het is belangrijk te begrijpen op welk moment init-blokken worden aangeroepen, hoe parameters worden doorgegeven en hoe delegatie de volgorde van initialisatie beïnvloedt.
Voorbeeld van basisdelegatie:
class Person(val name: String) { constructor(name: String, age: Int) : this(name) { println("Secundaire constructor: $name, $age") } }
Bij gebruik van overerving:
open class Parent(val name: String) class Child : Parent { constructor(name: String) : super(name) { println("Child secundair: $name") } }
Kan een secondary constructor nergens naar delegeren?
Nee, de compiler vereist een expliciete aanroep van this(...) of super(...), anders volgt er een fout.
In welke volgorde worden initialisaties en init-blokken uitgevoerd wanneer een secondary constructor wordt gebruikt?
Altijd wordt eerst de primary constructor en de init-blok(ken) aangeroepen, daarna de code van de secondary constructor.initialisatie.
class Demo(val value: String) { init { println("init blok") } constructor(value: String, code: Int) : this(value) { println("secundair: $code") } } Demo("kotlin", 7) // uitvoer: // init blok // secundair: 7
Kan een afgeleide alleen de primary constructor van de ouder aanroepen, als er ook een secondary constructor is?
Ja, maar alleen expliciet, via super(...), secundaire zijn niet direct zichtbaar voor afgeleiden.
In het project roept de secondary constructor de primary niet aan, cruciale initialisatie (bijv. het instellen van verplichte velden) gebeurt niet, wat leidt tot bugs en crashes in runtime.
Voordelen:
Nadelen:
Alle secondary constructors delegeren strikt via this(...), de benodigde initialisatie is gecentraliseerd in primary/init, de structuur is transparant voor onderhoud.
Voordelen:
Nadelen: