ProgrammationDéveloppeur Kotlin/Java

Comment fonctionne l'héritage des constructeurs en Kotlin, comment appelle-t-on le constructeur super et quels pièges existent lors de la combinaison des constructeurs primaires et secondaires ? Donnez des exemples pour différents cas, expliquez la différence avec Java.

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

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 :

  • Si la superclasse a un constructeur principal avec des paramètres obligatoires, la classe dérivée doit toujours l'appeler explicitement via : super(...).
  • Dans le constructeur secondaire, la classe de base est appelée via super(...) ou un autre constructeur secondaire/principal.
  • Aucun conflit d'initialisation n'est permis : tous les champs doivent toujours être correctement initialisés.

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 :

  • En Kotlin, il n'est pas permis de NE PAS appeler le constructeur de la superclasse.
  • Le constructeur principal initialise toujours les paramètres de base et peut être implicite.

Question piège

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 !

Exemples d'erreurs réelles dues à l'ignorance des subtilités de ce sujet


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.