Specificità di Kotlin nello sviluppo mobile: cosa sono, quali costrutti e come funzionano

Autore: IT Sectr Pubblicato: 2026-06-29 Tempo di lettura: 11 min

Kotlin è il linguaggio principale per lo sviluppo Android. Secondo Google Android Docs (2025), oltre il 95% dei nuovi progetti Android utilizza Kotlin. Comprendere le specificità di Kotlin — data class, sealed class, coroutine e scope functions — è un requisito obbligatorio per uno sviluppatore Android.

Punti Chiave

  • data class — generazione automatica di equals/hashCode/toString/copy/componentN. Per modelli dati. sealed class — gerarchia di tipi ristretta con controllo when.
  • Scope functions: let, run, with, apply, also. Si differenziano per contesto (it vs this) e valore restituito.
  • Coroutine: launch (fire-and-forget), async (con risultato), runBlocking (ponte), withContext (cambio Dispatcher).
  • lifecycleScope e viewModelScope — coroutine Lifecycle-aware senza cancellazione manuale.
  • reified — preservazione del tipo nelle funzioni inline. lateinit/lazy — inizializzazione differita.

Classi (data class, sealed class, object, companion object)

Kotlin estende i concetti di classe di Java. data class, sealed class, object e companion object — costrutti che non esistono in Java o sono implementati diversamente.

data class vs sealed class

data class — una classe che genera automaticamente equals(), hashCode(), toString(), copy() e componentN(). Ideale per modelli dati (DTO, Entity). Requisiti: almeno un parametro nel costruttore primario, val/var, non può essere open/sealed/inner. sealed class — una classe con una gerarchia di sottoclassi ristretta. Tutte le sottoclassi sono note in fase di compilazione e dichiarate nello stesso file. L'espressione when con sealed class non richiede un ramo else. sealed interface (Kotlin 1.9+) — come sealed class ma permette l'ereditarietà multipla. object — un singleton, dichiarato con la parola chiave object (non class). Inizializzazione lazy thread-safe. companion object — membri statici di una classe. Ha un nome (Companion di default). Può implementare interfacce e avere extension functions.

Tipo Descrizione Utilizzo
data classGenerazione automatica di equals, hashCode, toString, copyModelli dati, DTO, Entity
sealed classGerarchia ristretta, controllo whenStati, Risultato, UI State
sealed interfacesealed class + ereditarietà multiplaEventi, Azioni (Kotlin 1.9+)
objectSingleton (dichiarativo)Factory, Utility, Costanti
companion objectMembri statici della classeFactory Method, costanti statiche
enum classEnumerazione con costantiStati con insieme fisso

data class — per il 90% dei modelli. sealed class — per UI State e Risultato. object — per singleton. IT Sectr raccomanda sealed class per tutti gli stati dello schermo (Loading, Success, Error).

Sealed class in pratica

Sealed class — un potente strumento per modellare gli stati. Esempio: UiState<T> con sottoclassi Loading, Success(data: T), Error(message: String). L'espressione when garantisce la gestione di tutti gli stati. Sealed interface — per eventi e azioni dove è necessaria implementazione multipla. Value class (Kotlin 1.5+) — un wrapper per un singolo valore senza overhead. Usato per identificatori type-safe: @JvmInline value class UserId(val id: String).

Funzioni (extension, inline, higher-order, scope functions)

Extension Function — aggiungere un metodo a una classe esistente senza ereditarietà. fun String.isEmail(): Boolean. Extension Property — lo stesso per le proprietà (senza backing field). Inline Function — inserimento del corpo della funzione nel punto di chiamata — senza overhead di chiamata. Usato per higher-order functions con lambda. Higher-Order Function — una funzione che accetta o restituisce un'altra funzione. Scope Functions — cinque funzioni per lavorare con il contesto dell'oggetto: let, run, with, apply, also.

Scope Functions

let — contesto it, restituisce il risultato della lambda. Usato per chiamate null-safe (?.let {}). apply — contesto this, restituisce il contesto. Per configurazione dell'oggetto. run — contesto this, restituisce il risultato della lambda. Per calcoli con contesto. also — contesto it, restituisce il contesto. Per effetti collaterali (logging). with — non è extension, contesto this, restituisce il risultato della lambda. Per un gruppo di operazioni su un oggetto. Lambda — funzione anonima. Destructuring Declaration — decompressione di data class in variabili: val (name, age) = person.

Inline + reified

Inline function con reified — l'unico modo per preservare un tipo generico nella JVM. Usato per: builder type-safe (Gson.fromJson<T>()), controllo dei tipi (is T), ottenimento della classe (T::class). Crossinline e Noinline — modificatori per parametri lambda nelle funzioni inline. crossinline — vieta il non-local return, noinline — vieta l'inlining di una lambda specifica. IT Sectr raccomanda inline + reified solo quando si lavora con i tipi; per le normali higher-order functions, inline può aumentare la dimensione del bytecode.

Coroutine (Coroutine Builder, Dispatchers, Scope)

Coroutine — thread leggeri per la programmazione asincrona. Non bloccano il thread — si sospendono. suspend function — una funzione che può essere sospesa senza bloccare il thread. Può essere chiamata solo da una coroutine o da un'altra suspend function.

CoroutineScope

CoroutineScope — un ambito per le coroutine. Contiene CoroutineContext (Job + Dispatcher). lifecycleScope — per Activity/Fragment (Lifecycle-aware). viewModelScope — per ViewModel (cancellazione automatica a onCleared()). GlobalScope — ambito globale (non raccomandato in produzione — perdite di memoria). Dispatchers: Dispatchers.Main (UI), Dispatchers.IO (rete/disco), Dispatchers.Default (CPU-intensive), Dispatchers.Unconfined (non raccomandato). launch — avvia una coroutine: Job. async — avvia con risultato: Deferred<T>. runBlocking — ponte bloccante. withContext — cambia Dispatcher all'interno di una suspend function.

kotlin
// Esempio di coroutine: caricamento dati in ViewModel
class MainViewModel : ViewModel() {
    private val _state = MutableStateFlow<UiState>(UiState.Loading)
    val state: StateFlow<UiState> = _state.asStateFlow()

    fun loadData() {
        viewModelScope.launch {
            _state.value = UiState.Loading
            try {
                val data = withContext(Dispatchers.IO) {
                    repository.fetchData()
                }
                _state.value = UiState.Success(data)
            } catch (e: Exception) {
                _state.value = UiState.Error(e.message)
            }
        }
    }
}

// Richieste parallele con async
suspend fun loadCombinedData(): CombinedData = coroutineScope {
    val users = async(Dispatchers.IO) { api.getUsers() }
    val posts = async(Dispatchers.IO) { api.getPosts() }
    CombinedData(users.await(), posts.await())
}

viewModelScope.launch — avvio standard di coroutine in ViewModel. withContext(Dispatchers.IO) — passaggio al thread IO per richiesta di rete. Dispatchers determinano su quale pool di thread viene eseguita la coroutine. IT Sectr raccomanda viewModelScope per ViewModel e lifecycleScope per Activity/Fragment.

Funzionalità avanzate (reified, destructuring, lateinit/lazy)

reified — un modificatore di tipo nelle funzioni inline. Permette di usare il tipo: T::class, is T, as T. Senza reified, i generics nella JVM vengono cancellati (type erasure). inline fun + reified — una combinazione potente per API type-safe. Destructuring Declaration — val (x, y) = point. Funziona per data class e tipi con componentN(). typealias — alias di tipo: typealias Callback = (String) -> Unit. lateinit — inizializzazione differita di var (per dependency injection). Non thread-safe. lazy — inizializzazione lazy di val (thread-safe di default). lazy(LazyThreadSafetyMode.NONE) — senza sincronizzazione. Extension function e Extension property — aggiungere funzionalità senza ereditarietà. Kotlin è un linguaggio in cui le extension functions risolvono il 90% dei compiti di utilità.

Proprietà Delegata

Delegated Properties — delegare getter/setter a un altro oggetto. Delegati standard: lazy, observable, vetoable, map. Delegato personalizzato tramite operatori getValue/setValue. by — parola chiave di delega: val name by lazy { loadName() }. Le proprietà delegate sono la base per i delegati ViewModel (by viewModels()). IT Sectr raccomanda lazy per l'inizializzazione differita e Delegates.observable per osservare i cambiamenti.

Funzionalità Descrizione Esempio
reifiedPreservazione del tipo generico in inlineinline fun <reified T> parse(): T
destructuringDecompressione di data classval (name, age) = person
typealiasAlias di tipotypealias Orders = List<Order>
lateinitInizializzazione differita di varlateinit var adapter: Adapter
lazyInizializzazione lazy di valval config by lazy { load() }
delegatedDelega di proprietàvar x by Delegates.observable(0)

reified — per API type-safe. lazy — per caricamento differito. delegated properties — per riutilizzare la logica delle proprietà. IT Sectr raccomanda di padroneggiare tutte queste funzionalità per uno sviluppo efficace in Kotlin.

Flow e StateFlow

Flow — flusso di dati asincrono freddo in Kotlin. Emette valori su richiesta del collettore. StateFlow — Flow caldo con un unico valore corrente. Usato in ViewModel per UI State. SharedFlow — Flow caldo per eventi (eventi una tantum). flowOf, asFlow — creazione di Flow da collezioni. catch, retry, debounce — operatori. stateIn, shareIn — conversione di Flow freddo in caldo. IT Sectr raccomanda StateFlow per UI State e SharedFlow per eventi (Snackbar, navigazione).

kotlin
class SearchViewModel : ViewModel() {
    private val _query = MutableStateFlow("")
    val suggestions: StateFlow<List<String>> = _query
        .debounce(300)
        .filter { it.length >= 2 }
        .flatMapLatest { repository.search(it) }
        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())

    fun onQueryChanged(query: String) {
        _query.value = query
    }
}

Serializzazione (kotlinx.serialization, Parcelize)

kotlinx.serialization — libreria Kotlin per la serializzazione JSON. @Serializable — annotazione. @SerialName — nome campo personalizzato. Supporta: JSON, CBOR, ProtoBuf. Parcelize — @Parcelize per Android Parcelable (senza implementazione manuale). Gson vs Moshi vs kotlinx: kotlinx.serialization — Kotlin-first, compile-safe, senza reflection. Moshi — annotazioni + codegen. IT Sectr raccomanda kotlinx.serialization per nuovi progetti e Moshi per quelli esistenti.

kotlin
@Serializable
data class ApiResponse<T>(
    val success: Boolean,
    @SerialName("data") val data: T? = null,
    val error: String? = null
)

@Serializable
data class User(
    val id: Int,
    val name: String,
    val email: String
)

// Deserializzazione
val json = Json { ignoreUnknownKeys = true }
val response = json.decodeFromString<ApiResponse<List<User>>>(jsonString)
println("Users: ${response.data?.size ?: 0}")

Domande Frequenti

Qual è la differenza tra data class e sealed class?

data class — per dati (generazione automatica di equals/hashCode/copy). sealed class — per gerarchia di tipi (controllo in when). sealed interface — lo stesso con ereditarietà multipla.

Cosa sono le scope functions in Kotlin?

let, run, with, apply, also. Si differenziano per contesto (it vs this) e valore restituito (result vs context). let — null safety, apply — configurazione, also — effetti collaterali.

Cos'è CoroutineScope e quali tipi esistono?

CoroutineScope — un ambito per le coroutine. lifecycleScope — per Activity, viewModelScope — per ViewModel. GlobalScope — non raccomandato.

Cos'è reified in Kotlin?

reified — preservazione del tipo nelle funzioni inline. Permette T::class e is T. Funziona solo con funzioni inline.

Cosa sono i coroutine builder: launch, async, runBlocking?

launch — senza risultato. async — con risultato (Deferred). runBlocking — ponte bloccante per main/test. withContext — cambio Dispatcher.

Riepilogo

  • data class — per modelli. sealed class — per stati. object — per singleton.
  • Scope functions: let (null-safe), apply (configurazione), run (calcoli), also (logging).
  • Coroutine: launch (fire-and-forget), async (con risultato), withContext (cambio Dispatcher).
  • viewModelScope — standard per ViewModel. lifecycleScope — per Activity/Fragment.
  • reified — funzioni inline type-safe. lateinit — DI, lazy — inizializzazione lazy.
  • Extension functions — aggiungi funzionalità senza ereditarietà.
  • Dispatchers: Main (UI), IO (rete/disco), Default (CPU). Scegli quello giusto.

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.

Discuti il progetto