sealed class e sealed interface in Kotlin sono meccanismi di gerarchia limitata dei tipi, dove tutte le possibili sottoclassi sono note in fase di compilazione. A differenza delle classi astratte ordinarie, sealed class garantisce una gestione esaustiva di tutte le varianti in un'espressione when. Secondo la documentazione JetBrains Kotlin Language Guide (2026), i tipi sealed sono la base per modellare stati, schermate UI e tipi di risultato nei progetti Kotlin.
Punti chiave
sealed class è una classe astratta con una restrizione: tutte le sue sottoclassi dirette devono essere dichiarate nello stesso file della classe sealed stessa. Questa restrizione rende la gerarchia chiusa (sealed) — nessun codice al di fuori del file può aggiungere una nuova sottoclasse.
sealed interface, aggiunta in Kotlin 1.5, fornisce la stessa garanzia ma con la flessibilità di un'interfaccia: una sealed interface può essere implementata da più classi, oggetti o altre interfacce in un file. A differenza di sealed class, sealed interface non ha restrizione di ereditarietà singola — una classe può implementare più interfacce sealed contemporaneamente.
Secondo Kotlin Evolution and Roadmap (2026), sealed interface è stata aggiunta su richiesta della comunità per una modellazione più flessibile. La motivazione principale è la capacità di combinare gerarchie di tipi indipendenti senza ereditarietà multipla di classi.
La dichiarazione di una sealed class inizia con il modificatore sealed prima di class. Le sottoclassi vengono dichiarate nello stesso file.
sealed class NetworkResult {
data class Success(val data: String) : NetworkResult()
data class Error(val message: String) : NetworkResult()
object Loading : NetworkResult()
}
Ogni sottoclasse di una sealed class può avere le proprie proprietà e metodi. Loading è un singleton (object), Success e Error sono data class con parametri. Il compilatore conosce tutte e tre le varianti e verifica la loro completezza quando utilizzate in when.
Le classi sealed possono essere annidate, creando gerarchie multilivello per modelli di dati complessi senza perdere la type safety.
sealed class UiState {
object Idle : UiState()
object Loading : UiState()
data class Content(val items: List<Item>) : UiState()
data class Error(val exception: Throwable) : UiState()
}
sealed interface viene dichiarata in modo simile a sealed class, ma permette di implementare più interfacce sealed in una singola classe.
sealed interface Action
sealed interface Loggable
data class Navigate(val route: String) : Action, Loggable
data class ShowToast(val text: String) : Action
object GoBack : Action, Loggable
La classe Navigate implementa due interfacce sealed contemporaneamente — Action e Loggable. Ciò è impossibile con sealed class a causa della restrizione di ereditarietà singola. sealed interface fornisce la flessibilità di combinare gerarchie indipendenti.
sealed interface è preferibile quando la gerarchia non richiede stato condiviso o costruttore. Secondo le JetBrains Kotlin Guidelines (2026), sealed interface dovrebbe essere usata per impostazione predefinita per tutte le nuove gerarchie dove non è necessario un costruttore comune, rendendo il codice più flessibile per estensioni future.
Il principale vantaggio dei tipi sealed è la gestione esaustiva nell'espressione when. Il compilatore verifica che tutte le possibili sottoclassi siano coperte.
fun handleResult(result: NetworkResult): String = when (result) {
is NetworkResult.Success -> "Data: ${result.data}"
is NetworkResult.Error -> "Error: ${result.message}"
is NetworkResult.Loading -> "Loading..."
// else non è richiesto — il compilatore sa che tutte le varianti sono coperte
}
Se uno sviluppatore aggiunge una nuova sottoclasse a una gerarchia sealed ma dimentica di gestirla in when — il compilatore genererà un errore. Questa è sicurezza a livello di tipi, non disponibile con gerarchie aperte che usano il ramo else.
Secondo Google Android Developers (2026), le classi sealed sono il modo raccomandato per modellare lo stato dell'UI in Jetpack Compose. La verifica esaustiva di when previene stati in cui lo sviluppatore non ha gestito tutte le possibili varianti di visualizzazione di una schermata.
enum class e sealed class sono spesso confuse, ma hanno scopi e capacità diversi.
| Caratteristica | sealed class | enum class |
|---|---|---|
| Istanze | Multiple (data class), singola (object) | Esattamente una per costante |
| Proprietà | Diverse per ogni sottoclasse | Identiche per tutte le costanti |
| Ereditarietà | Sì (da sealed class) | No (final implicito) |
| Costruttore | Può avere parametri | Solo condiviso per tutte le costanti |
| Gerarchia | Limitata, sealed | Insieme fisso di costanti |
La scelta tra sealed class e enum class dipende dal compito. Se le varianti non portano dati aggiuntivi — usa enum. Se ogni variante contiene campi unici — usa sealed class o sealed interface.
I tipi sealed vengono utilizzati nei progetti Kotlin per una serie di scenari standard in cui è necessaria una modellazione type-safe.
Ogni schermata Compose può avere una sealed class UiState che descrive tutti gli stati possibili: Idle, Loading, Content(data), Error(exception). L'espressione when garantisce che tutti gli stati siano gestiti.
NetworkResult con le varianti Success, Error, Loading è un pattern standard nei progetti Kotlin con Retrofit e Ktor. sealed class garantisce una gestione sicura di ogni risultato di richiesta.
sealed interface per le rotte di navigazione permette ai moduli di dichiarare le proprie rotte rimanendo all'interno di una gerarchia unificata. Ciò elimina errori con rotte sconosciute in fase di compilazione.
Secondo KotlinConf (2025), sealed class e sealed interface sono il fondamento del design type-safe nelle applicazioni Kotlin moderne. Si combinano con data class per modellare strutture di dominio complesse senza perdere la sicurezza in fase di compilazione.
Domande frequenti
Tutte le sottoclassi dirette di una sealed class devono essere dichiarate nello stesso file. Per sealed interface vale la stessa regola — implementazioni in un file.
No, la regola del file singolo si applica anche a sealed interface. Tutte le implementazioni devono essere nel file in cui è dichiarata la sealed interface.
sealed interface non ha stato o costruttore e permette implementazione multipla. sealed class può avere costruttore e stato condiviso, ma una classe può ereditare solo una sealed class.
Il compilatore verifica la completezza di when: se non tutte le sottoclassi sono gestite, il codice non compila. Questo elimina errori a runtime e rende il codice più sicuro.
Sì, una sealed class può avere un costruttore (privato di default). Tutte le sottoclassi possono passare parametri a questo costruttore tramite super().
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche