ProgrammazioneSviluppatore Backend

Cosa sono le classi inline (value class) in Kotlin, a cosa servono e quali sono i limiti del loro utilizzo?

Supera i colloqui con l'assistente IA Hintsage

Risposta.

Storia della domanda

In Kotlin è stata introdotta la concezione delle classi inline/value (ora chiamate value class), per ridurre l'overhead runtime nella gestione di wrapper su primitivi e piccole strutture. L'idea è presa in prestito da altri linguaggi (ad esempio, le strutture C#), dove tale ottimizzazione è utile per aumentare le prestazioni senza perdere la tipizzazione.

Problema

Creare classi wrapper (ad esempio per tipi entità o identificatori) senza ottimizzazione porta alla creazione di un oggetto aggiuntivo in memoria, il che influisce sulle prestazioni, GC e può portare a Boxing/Unboxing overhead. Spesso si desidera avere una tipizzazione rigorosa (ad esempio, UserId invece di Int), ma senza la reale creazione di oggetti.

Soluzione

La value class è dichiarata con il modificatore value. Nella maggior parte delle situazioni, la JVM non crea un oggetto aggiuntivo — la value class viene sostituita direttamente dal suo campo (inlining). Questo fornisce type-safety e prestazioni simili a "solo Int".

Esempio di codice:

@JvmInline value class UserId(val value: Int) fun showId(id: UserId) = println(id.value) val id = UserId(15) showId(id) // Senza creare un oggetto separato UserId

Caratteristiche principali:

  • La classe deve contenere esattamente una proprietà (val o var), ma questo tipo non può essere nullable
  • Nessun supporto per l'ereditarietà (la value class non può ereditare né essere ereditata)
  • Alcuni vincoli: non è possibile avere un blocco init, memorizzare proprietà lateinit o non inizializzate, non è possibile utilizzare la riflessione in tutti i casi

Domande trabocchetto.

Possono le value class avere più proprietà?

No, la value class può contenere solo una proprietà.

// Errore: // value class Money(val amount: Int, val currency: String)

È possibile creare una value class con una proprietà nullable?

Il campo value della value class non può essere nullable — solo tipi non-nullable.

// Errore: // value class Name(val value: String?)

È possibile utilizzare l'ereditarietà con le value class?

La value class non supporta l'ereditarietà e non può essere astratta o sealed.

// Errore: // value class NewId(val value: Int): BaseId()

Errori comuni e anti-pattern

  • Tentativo di utilizzare la value class per strutture complesse (ad esempio, con più campi)
  • Memorizzare valori nullable attraverso value class
  • Utilizzare metodi di riferimento (ad esempio, i metodi equals/hashCode possono comportarsi in modo inaspettato nel backend compilato)

Esempio dalla vita reale

Caso negativo

Un sviluppatore ha creato una value class per un'entità con due proprietà (ad esempio, una coppia di Int e String), ricevendo un errore di compilazione.

Pro:

  • Cerca di ottenere un tipo rigoroso Contro:
  • Non funziona, impossibile compilare

Caso positivo

Un sviluppatore utilizza una value class per un tipo identificatore con un campo (ad esempio, UserId), il che funziona rapidamente e in sicurezza.

Pro:

  • Codice conciso e sicuro
  • Nessun overhead runtime Contro:
  • Può essere utilizzato solo con un singolo tipo non-nullable