ProgrammationDéveloppeur Kotlin

Expliquez les subtilités de la visibilité et de l'héritage des constructeurs en Kotlin : quelles sont les différences entre le constructeur primaire et les constructeurs secondaires, les nuances de l'héritage et des modificateurs de visibilité. Donnez des exemples de code et des erreurs typiques.

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

En Kotlin, toute classe peut avoir un constructeur primaire (indiqué dans la déclaration de la classe) et plusieurs constructeurs secondaires (via constructor).

  • Le constructeur primaire ne peut pas contenir de code en dehors de la déclaration (la logique se trouve dans init).
  • Les constructeurs secondaires mettent en œuvre des variantes supplémentaires d'initialisation.
  • Si le parent n'a pas de constructeur sans paramètres, l'héritier doit appeler explicitement son constructeur.
  • À l'aide des modificateurs (private, protected, internal, public), on peut masquer ou restreindre la visibilité des constructeurs.

Exemple avec un constructeur primaire et des constructeurs secondaires :

open class Person(val name: String) { constructor(name: String, age: Int) : this(name) { // constructeur secondaire } } class Employee : Person { constructor(name: String) : super(name) // Appel super explicite nécessaire }

Modificateurs de visibilité :

class Secret private constructor() { companion object { fun create() = Secret() } } val s = Secret.create() // Ok, mais Secret() - erreur

Nuances :

  • Si une classe avec un constructeur primaire a des paramètres, il est impossible d'hériter sans transmettre ces paramètres.
  • Les constructeurs secondaires doivent indirectement ou directement appeler le constructeur primaire.
  • Les classes imbriquées n'ont pas accès au constructeur private de la classe externe.

Question piège.

Peut-on hériter d'une classe en Kotlin sans appeler son constructeur primaire ?

Réponse : Non. En Kotlin, lors de l'héritage, au moins un constructeur du parent doit toujours être appelé — soit le primaire, soit un secondaire (via super()).

Exemple :

open class A(val x: Int) class B: A // Erreur : le constructeur A doit être appelé explicitement

Exemples d'erreurs réelles dues à l'ignorance des subtilités du sujet.


Histoire

L'équipe a essayé d'interdire la création directe d'objets de la classe et a rendu le constructeur private. Cependant, ils ont oublié de mettre en œuvre la méthode de fabrique. Cela a conduit à l'impossibilité de tester la classe sans réflexion et a bloqué CI.


Histoire

Ils ont hérité d'une classe avec des paramètres obligatoires dans le constructeur primaire, mais ne les ont pas transmis lors de la déclaration de l'héritier. Cela n'a été découvert qu'au stade de la compilation après un long débogage.


Histoire

Lors de l'utilisation de constructeurs secondaires, ils ont oublié que tous doivent appeler le primaire. En conséquence, les objets ont été initialisés sans les paramètres nécessaires, provoquant un NullPointerException à l'exécution.