Ce face lazy
val x by lazy { calcul } declară o proprietate al cărei calcul nu se face la creare, ci prima dată când citești x. Rezultatul este reținut, așa că a doua citire nu mai rulează blocul. Este util pentru valori scumpe (citirea unui fișier, o listă mare) care poate nici nu sunt folosite.
Cuvântul by înseamnă că proprietatea este delegată obiectului returnat de lazy. Funcționează doar cu val, pentru că valoarea nu se mai poate schimba după calcul. Implicit, lazy este sigur pentru mai multe fire de execuție: blocul rulează o singură dată chiar dacă două fire citesc deodată.
Parametri
| Parametru | Descriere |
|---|---|
initializer: () -> T |
Blocul care calculează valoarea; ultima expresie este valoarea. |
Ce returnează
Un obiect Lazy<T>; prin by lucrezi direct cu valoarea de tip T.
Exemple
Exemplul 1: Calculul se face doar la prima citire
Mesajul „Calculez…” apare o singură dată, abia după „Obiect creat”: valoarea este calculată la prima folosire și apoi refolosită.
class Raport(private val vanzari: List<Double>) {
val total: Double by lazy {
println("Calculez totalul...")
vanzari.sum()
}
}
fun main() {
val raport = Raport(listOf(120.0, 80.5, 300.0))
println("Obiect creat")
println("Total: ${raport.total} lei")
println("Din nou: ${raport.total} lei")
}
Rezultat
Obiect creat
Calculez totalul...
Total: 500.5 lei
Din nou: 500.5 lei
Exemplul 2: lazy la nivelul unui fișier
Lista de orașe se construiește doar dacă programul ajunge s-o folosească.
val orase: List<String> by lazy {
println("(încarc lista de orașe)")
listOf("Iași", "Cluj-Napoca", "Timișoara", "Brașov").sorted()
}
fun main() {
println("Pornire")
println(orase.first())
println(orase.size)
}
Rezultat
Pornire
(încarc lista de orașe)
Brașov
4
Greșeli frecvente
- Scrii
var x by lazy { }. Nu compilează: lazy merge doar cuval. Pentru o variabilă inițializată mai târziu foloseștelateinit var. - Pui în bloc ceva ce trebuie recalculat la fiecare citire (ora curentă, conținutul unui fișier care se schimbă). lazy calculează o singură dată; pentru recalcul folosește un getter:
val x get() = ....