En Kotlin, chaque classe peut avoir un constructeur principal (primary) et plusieurs constructeurs secondaires (secondary). La délégation de constructeur est un mécanisme où un constructeur secondaire doit obligatoirement appeler soit le constructeur principal directement, soit un autre constructeur secondaire de la même classe (et finalement - le principal). Si une classe hérite d'une autre, chaque constructeur secondaire de la classe fille doit explicitement déléguer l'appel au constructeur de la classe parente, si nécessaire.
En Java, les constructeurs peuvent s'appeler directement entre eux à l'aide de this() ou super(), en surchargeant les constructeurs dans différentes combinaisons. En Kotlin, ce concept est formalisé : une classe ne peut avoir qu'un seul constructeur principal, les constructeurs secondaires peuvent utiliser la logique de délégation, qui doit être explicitement indiquée.
Une mise en œuvre incorrecte de la délégation peut entraîner des erreurs de compilation : il n'est pas possible de ne pas appeler le constructeur principal s'il est déclaré, ou de ne pas appeler le constructeur super dans une classe héritée, si la classe de base n'a pas de constructeur par défaut. Il est important de comprendre à quel moment les blocs init sont appelés, comment les paramètres sont transmis, et comment la délégation influence l'ordre d'initialisation.
Exemple de base de délégation :
class Person(val name: String) { constructor(name: String, age: Int) : this(name) { println("Constructeur secondaire : $name, $age") } }
Si l'héritage est utilisé :
open class Parent(val name: String) class Child : Parent { constructor(name: String) : super(name) { println("Enfant secondaire : $name") } }
Un constructeur secondaire peut-il ne pas déléguer ?
Non, le compilateur exigera un appel explicite à this(...) ou super(...), sinon il y aura une erreur.
Dans quel ordre sont exécutées les initialisations et les blocs init lors de l'utilisation d'un constructeur secondaire ?
Le constructeur principal et le(s) bloc(s) init sont toujours appelés en premier, puis le code d'initialisation du constructeur secondaire.
class Demo(val value: String) { init { println("bloc init") } constructor(value: String, code: Int) : this(value) { println("secondaire : $code") } } Demo("kotlin", 7) // sortie : // bloc init // secondaire : 7
Un descendant peut-il appeler uniquement le constructeur principal du parent, même s'il y a un constructeur secondaire ?
Oui, mais seulement explicitement, via super(...), les secondaires ne sont pas visibles pour les descendants directement.
Dans un projet, le constructeur secondaire ne déclenche pas le principal, ce qui empêche l'initialisation vitale (par exemple, la définition de champs obligatoires) et entraîne des bogues et des plantages à l'exécution.
Avantages:
Inconvénients:
Tous les constructeurs secondaires délèguent strictement via this(...), l'initialisation nécessaire est centralisée dans le principal/init, la structure est transparente pour la maintenance.
Avantages:
Inconvénients: