Le classi annidate (nested) e interne (inner) in Kotlin sono utilizzate per la raggruppamento logico e l'incapsulamento della funzionalità all'interno di una classe esterna.
L'idea delle classi annidate proviene da Java come modo per strutturare il codice e isolare i componenti ausiliari all'interno della classe principale. In Kotlin la sintassi e l'approccio sono stati ereditati da Java, ma con importanti differenze.
La principale sfida è separare in modo appropriato le classi ausiliarie lì dove non dovrebbero esistere al di fuori del contesto della classe esterna, ma è comunque necessaria una diversa misura di accesso ai membri della classe esterna. In Java, per impostazione predefinita, una classe annidata è una classe interna, mentre in Kotlin, per impostazione predefinita, è annidata (statica).
In Kotlin, per impostazione predefinita, la dichiarazione di una classe all'interno di un'altra crea una classe statica (nested), il che significa che questa classe non ha accesso ai membri della classe esterna. Per ottenere l'accesso si utilizza la parola chiave inner.
Esempio di codice:
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" } }
Caratteristiche chiave:
class Nested) per impostazione predefinita non ha un riferimento all'istanza esterna;inner class Inner) ha un riferimento e può accedere ai membri della classe esterna, anche a quelli privati;Può una classe annidata (nested) accedere a una proprietà privata della classe esterna?
No, la classe annidata (per impostazione predefinita) in Kotlin è statica e non contiene un riferimento alla classe esterna, quindi non ha accesso alle sue proprietà e metodi.
Qual è la differenza tra le classi inner in Kotlin e Java?
In Java, la classe annidata per impostazione predefinita non è statica e ha un riferimento all'esterno. In Kotlin, al contrario; la classe annidata è statica, solo la classe inner ottiene un riferimento all'istanza esterna.
È possibile dichiarare una classe interna in un oggetto (object)?
No, la classe interna (inner) non può essere dichiarata all'interno di un oggetto, perché l'oggetto non può essere istanziato.
Il programmatore dichiara una classe inner che non utilizza le proprietà della classe esterna:
class Container { inner class Helper { fun help() = "help" } }
Pro:
La classe è facilmente accessibile dall'oggetto esterno.
Contro:
Uso della classe inner per implementare l'accesso allo stato privato della classe esterna:
class Auth { private var token: String = "" inner class TokenManager { fun updateToken(new: String) { token = new } } }
Pro:
Contro: