Ce face get și set (getteri și setteri)
Orice proprietate Kotlin are un getter (rulează la citire) și, dacă este var, un setter (rulează la atribuire). Implicit ei doar citesc și scriu valoarea. Îi poți rescrie sub declarație: get() = ... calculează valoarea la fiecare citire, iar set(value) { ... } poate valida sau transforma valoarea primită.
În setter (și în getter), valoarea păstrată se numește field (backing field). Scrii field = value, nu pret = value: atribuirea către proprietate ar apela din nou setterul, la nesfârșit.
Poți schimba vizibilitatea setterului fără să-l rescrii: var sold = 0; private set înseamnă că oricine poate citi soldul, dar doar clasa îl poate modifica.
Exemple
Exemplul 1: Getter calculat
numeComplet și majora nu păstrează nimic: se calculează la fiecare citire, deci urmăresc schimbările.
class Persoana(var prenume: String, var nume: String, var varsta: Int) {
val numeComplet: String
get() = "$prenume $nume"
val majora get() = varsta >= 18
}
fun main() {
val p = Persoana("Ioana", "Marin", 17)
println("${p.numeComplet}, majoră: ${p.majora}")
p.varsta = 18
p.nume = "Pop"
println("${p.numeComplet}, majoră: ${p.majora}")
}
Rezultat
Ioana Marin, majoră: false
Ioana Pop, majoră: true
Exemplul 2: Setter cu validare și field
Setterul refuză notele în afara intervalului 1-10 și păstrează valoarea veche. field este valoarea memorată.
class Nota(valoareInitiala: Int) {
var valoare: Int = valoareInitiala
set(value) {
if (value in 1..10) {
field = value
} else {
println("Nota $value este invalidă, rămâne $field")
}
}
}
fun main() {
val n = Nota(7)
n.valoare = 9
println("Nota: ${n.valoare}")
n.valoare = 15
println("Nota: ${n.valoare}")
}
Rezultat
Nota: 9
Nota 15 este invalidă, rămâne 9
Nota: 9
Exemplul 3: private set
vizite se citește din afară, dar se modifică doar prin metoda inregistreaza. Setterul personalizat de la oras transformă textul la fiecare atribuire.
class Pagina(val adresa: String) {
var vizite = 0
private set
var oras: String = ""
set(value) { field = value.trim().replaceFirstChar { it.uppercase() } }
fun inregistreaza() { vizite++ }
}
fun main() {
val p = Pagina("/invata/kotlin/")
repeat(3) { p.inregistreaza() }
p.oras = " timișoara "
println("${p.adresa}: ${p.vizite} vizite din ${p.oras}")
}
Rezultat
/invata/kotlin/: 3 vizite din Timișoara
Greșeli frecvente
- Scrierea
set(value) { pret = value }: setterul se apelează pe el însuși la infinit și programul se oprește cuStackOverflowError. Foloseștefield = value. - Un getter calculat cu inițializare (
val x: Int = 5 get() = 10): dacă getterul nu foloseștefield, nu există valoare de inițializat (eroareinitializer is prohibited here because this property has no backing field). - Calcule scumpe în
get(): rulează la fiecare citire. Pentru o valoare calculată o singură dată foloseșteby lazy.
Comenzi înrudite
val și var: val declară o variabilă care nu mai poate fi schimbată după atribuire; var declară una care poate primi altă valoare.class: class declară o clasă: un tip nou care grupează date (proprietăți) și comportament (metode).lateinit: lateinit permite unei proprietăți var ne-nullable să primească valoare mai târziu, după crearea obiectului.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.private și protected: private ascunde o declarație în clasa sau fișierul ei; protected o face vizibilă și în subclase.