Ce face lateinit
O proprietate ne-nullable trebuie să primească valoare la creare. Uneori valoarea vine mai târziu: dintr-o metodă de configurare, dintr-un framework (Android, teste) sau după citirea unui fișier. În loc s-o faci nullable și să scrii !! peste tot, o marchezi lateinit var: compilatorul te lasă s-o declari fără valoare.
Dacă citești proprietatea înainte să-i dai valoare, programul aruncă UninitializedPropertyAccessException, cu numele proprietății în mesaj. Poți verifica înainte cu this::nume.isInitialized.
Restricții: doar var, tipul nu poate fi nullable și nu poate fi primitiv (Int, Double, Boolean). Pentru valori calculate o singură dată, la prima folosire, alege by lazy.
Exemple
Exemplul 1: Valoare primită după creare
conexiune primește valoare în porneste(). După aceea se folosește ca o proprietate obișnuită, fără ?. sau !!.
class Serviciu {
lateinit var conexiune: String
fun porneste(server: String) {
conexiune = "conectat la $server"
}
fun trimite(mesaj: String) = println("[$conexiune] $mesaj")
}
fun main() {
val s = Serviciu()
s.porneste("db.exemplu.ro")
s.trimite("Salut")
s.trimite("Comanda 15 a fost plătită")
}
Rezultat
[conectat la db.exemplu.ro] Salut
[conectat la db.exemplu.ro] Comanda 15 a fost plătită
Exemplul 2: Citire înainte de inițializare
Mesajul excepției spune exact care proprietate nu a primit valoare.
class Raport {
lateinit var titlu: String
}
fun main() {
val r = Raport()
try {
println(r.titlu)
} catch (e: UninitializedPropertyAccessException) {
println("Eroare: ${e.message}")
}
r.titlu = "Vânzări octombrie"
println(r.titlu)
}
Rezultat
Eroare: lateinit property titlu has not been initialized
Vânzări octombrie
Exemplul 3: Verificare cu isInitialized
this::utilizator este o referință la proprietate; isInitialized spune dacă a primit valoare.
class Sesiune {
lateinit var utilizator: String
fun stare() = if (this::utilizator.isInitialized) "autentificat ca $utilizator" else "neautentificat"
}
fun main() {
val s = Sesiune()
println(s.stare())
s.utilizator = "ana.pop"
println(s.stare())
}
Rezultat
neautentificat
autentificat ca ana.pop
Greșeli frecvente
lateinit var varsta: Int: nu este permis pentru tipuri primitive (eroare'lateinit' modifier is not allowed on properties of primitive types). FoloseșteInt?sau o valoare inițială.lateinit val: nu se poate,lateinitmerge doar cuvar.- Folosirea lui
lateinitpentru a evita gândirea desprenull: dacă proprietatea poate rămâne fără valoare în mod normal, tipul nullable este mai cinstit.
Comenzi înrudite
null și null safety (?. ?: !!): null înseamnă „nicio valoare”. Kotlin separă tipurile care acceptă null (String?) și oferă ?., ?: și !! pentru ele.lazy: Creează o valoare calculată abia la prima folosire, apoi păstrată; se folosește cu val nume by lazy { … }.get și set (getteri și setteri): get și set definesc ce se întâmplă când o proprietate este citită sau modificată; field este valoarea păstrată în spate.val și var: val declară o variabilă care nu mai poate fi schimbată după atribuire; var declară una care poate primi altă valoare.Proprietăți delegate (by lazy, observable, map): O proprietate delegată (val x by …) lasă un alt obiect să decidă ce se întâmplă la citire și scriere: lazy, observable, map.