En Kotlin, une classe peut avoir un constructeur principal et autant de constructeurs secondaires que nécessaire. La différence avec Java est que le constructeur principal est déclaré dans l'en-tête de la classe et peut contenir des paramètres et des modificateurs. Les constructeurs secondaires doivent toujours appeler soit un autre constructeur secondaire, soit le constructeur principal, soit le constructeur de la superclasse (via le mot-clé super).
Caractéristiques clés :
: super(...).super(...) ou un autre constructeur secondaire/principal.Exemple d'utilisation avec héritage :
open class A(val a: Int) { constructor(a: Int, str: String) : this(a) { println("Constructeur secondaire dans A: $str") } } class B : A { constructor(a: Int) : super(a) { println("Constructeur secondaire dans B") } constructor(a: Int, s: String) : super(a, s) { println("Constructeur secondaire #2 dans B") } }
Comment cela diffère de l'approche Java :
Peut-on en Kotlin créer une classe dérivée SANS appeler explicitement le constructeur de la superclasse, si la classe de base a seulement un certain constructeur ?
Réponse : Non, contrairement à Java, en Kotlin, l'appel au constructeur de la superclasse est obligatoire et doit être explicitement indiqué soit dans l'en-tête de la classe, soit après le mot-clé : super().
Exemple d'erreur :
open class Base(val x: Int) class Derived : Base // Erreur de compilation !
Histoire
Dans un projet de microservices après la migration vers Kotlin, ils ont oublié l'indication explicite du constructeur parent : le constructeur de la superclasse avec un paramètre obligatoire n'a pas été appelé, le service ne compilait pas, il a fallu refactoriser les signatures.
Histoire
Un projet Android avait une hiérarchie profonde (Activity → BaseActivity → CustomActivity), l'ajout d'un constructeur secondaire perdait des paramètres, ce qui entraînait l'appel d'un constructeur de base incorrect, et une partie des champs restait null - l'application échouait à l'exécution avec une NPE.
Histoire
Dans le code d'une bibliothèque ouverte, un constructeur secondaire dans une classe dérivée a accidentellement évité le constructeur principal, ce qui a conduit à deux branches d'initialisation différentes : parfois le champ était initialisé, parfois non. L'erreur n'a été trouvée qu'après beaucoup de temps grâce à des rapports de bogues complexes.