Le funzioni di scope in Kotlin sono funzioni standard (let, also, run, apply, with) che consentono di gestire il contesto di esecuzione di un blocco di codice per un oggetto. Esse differiscono per:
it o this.| Funzione | this/it | Restituisce | Per cosa? |
|---|---|---|---|
| let | it | risultato | catena di operazioni, lavoro con nullable, mappa |
| also | it | oggetto | effetti collaterali, logging, debug |
| run | this | risultato | calcoli, inizializzazione con restituzione |
| apply | this | oggetto | configurazione dell'oggetto, builders |
| with | this | risultato | lavoro con API esterne, oggetto "esterna" |
Esempi:
let: comodo se l'oggetto è nullable:val str: String? = "Text" str?.let { println(it.length) }
apply: configurazione dell'oggetto:val paint = Paint().apply { color = Color.RED strokeWidth = 2f }
run: esecuzione su un oggetto, restituisce il risultato:val length = "abcde".run { length }
with: per lavorare con un oggetto esterno:val sb = StringBuilder() with(sb) { append("Hello, ") append("world!") toString() }
also: per effetti collaterali (ad esempio, log):val list = mutableListOf(1, 2, 3) list.also { println("Prima: $it") }.add(4)
it, non è molto comodo cambiare le proprietà dell'oggetto.this / it), utile per i builders.with è una funzione normale, non un'extension.Qual è la differenza tra let e also?
Risposta:
it all'interno del blocco,let restituisce il risultato della lambda, spesso utilizzato per catene di trasformazione,also restituisce l'oggetto originale, utilizzato per effetti collaterali (log, debug), così da non intervenire nella catena di trasformazione.Esempio:
val result = listOf(1).also { println(it) }.map { it * 2 } // risultato — List<Int>
Storia
Un principiante ha usato let per configurare un oggetto, pensando che così potesse cambiare il suo stato "in catena". Di conseguenza, al termine del blocco di configurazione otteneva non l'oggetto, ma il risultato della lambda (ad esempio, nulla), rompendo così la catena di costruzione del DSL.
Storia
Durante la scrittura del codice per lavorare con oggetti nullable, hanno usato run invece di let, non notando la differenza nel valore restituito. Di conseguenza, il risultato dell'espressione differiva da quello atteso, apparivano null dove non avrebbero dovuto esserci — la logica dell'applicazione si rompeva.
Storia
In un grande builder, hanno accidentalmente usato with per oggetti interni, sperando nel pattern extension. Poiché with non è una funzione di estensione, la catena di più blocchi with non funzionava correttamente, le chiamate interne si confondevano e uscivano dai confini dell'oggetto attuale. È stato necessario riscrivere completamente la gerarchia di creazione degli oggetti.