Les classes imbriquées (nested) et internes (inner) en Kotlin sont utilisées pour le groupement logique et l'encapsulation de fonctionnalités à l'intérieur d'une classe externe.
L'idée des classes imbriquées provient de Java comme un moyen de structurer le code et d'isoler des composants auxiliaires à l'intérieur de la classe principale. En Kotlin, la syntaxe et l'approche sont héritées de Java, mais avec des différences importantes.
Le principal défi est de bien séparer les classes auxiliaires là où elles ne devraient pas exister en dehors du contexte de la classe externe, tout en nécessitant différents niveaux d'accès aux membres de la classe externe. En Java, par défaut, une classe imbriquée est une classe interne, tandis qu'en Kotlin, par défaut, elle est imbriquée (statique).
En Kotlin, par défaut, la déclaration d'une classe à l'intérieur d'une autre crée une classe statique (nested), c'est-à-dire que cette classe n'a pas accès aux membres de la classe externe. Pour obtenir l'accès, on utilise le mot-clé inner.
Exemple de code:
class Outer { private val secret = "outside" class Nested { fun call() = "nested: no access to Outer.secret" } inner class Inner { fun call() = "inner: can access $secret" } }
Caractéristiques clés :
class Nested) n'a par défaut pas de référence à l'instance de la classe externe ;inner class Inner) a une référence et peut accéder aux membres de la classe externe, même aux privés ;Une classe imbriquée (nested) peut-elle accéder à une propriété privée de la classe externe ?
Non, la classe imbriquée (par défaut) en Kotlin est statique et ne contient pas de référence à la classe externe, donc elle n'a pas accès à ses propriétés et méthodes.
Quelle est la différence entre les classes internes en Kotlin et en Java ?
En Java, une classe imbriquée par défaut n'est pas statique et a une référence à l'externe. En Kotlin, au contraire ; une classe imbriquée est statique, seule la classe interne reçoit une référence à l'instance externe.
Peut-on déclarer une classe interne dans un objet (object) ?
Non, une classe interne (inner) ne peut pas être déclarée à l'intérieur d'un objet, car l'objet ne peut pas être instancié.
Un développeur déclare une classe interne, qui n'utilise pas les propriétés de la classe externe :
class Container { inner class Helper { fun help() = "help" } }
Avantages :
La classe est facilement accessible depuis l'objet externe.
Inconvénients :
Utilisation d'une classe interne pour implémenter l'accès à l'état privé de la classe externe :
class Auth { private var token: String = "" inner class TokenManager { fun updateToken(new: String) { token = new } } }
Avantages :
Inconvénients :