Ce face Destructuring (val (a, b) = ...)
Declarația val (a, b) = obiect creează două variabile și le dă valorile obiect.component1() și obiect.component2(). Funcțiile componentN există automat pentru data class (în ordinea proprietăților din constructor), Pair, Triple, elementele unui Map și liste (primele cinci elemente).
Destructuring merge în for (for ((oras, temp) in temperaturi)), în parametrii unei lambda (map { (nume, nota) -> ... }) și la valorile returnate de funcții (o funcție poate returna un Pair sau o data class). O componentă care nu te interesează se înlocuiește cu _.
Destructuring se face după poziție, nu după nume: în val (oras, nume) = persoana, oras primește tot prima proprietate. Pentru clasele tale poți scrie funcții operator fun component1().
Exemple
Exemplul 1: Data class, Pair și funcție care returnează două valori
minMax returnează un Pair, desfăcut direct în două variabile.
data class Elev(val nume: String, val clasa: String, val medie: Double)
fun minMax(note: List<Int>): Pair<Int, Int> = note.min() to note.max()
fun main() {
val elev = Elev("Ana Pop", "a X-a B", 9.45)
val (nume, clasa, medie) = elev
println("$nume este în clasa $clasa și are media $medie")
val (minim, maxim) = minMax(listOf(7, 10, 5, 9))
println("Nota minimă: $minim, maximă: $maxim")
}
Rezultat
Ana Pop este în clasa a X-a B și are media 9.45
Nota minimă: 5, maximă: 10
Exemplul 2: În for și în lambda, cu _
Elementele unui Map se desfac în cheie și valoare. În lambda, parantezele din jurul lui (nume, _, medie) arată destructuring; _ sare peste clasă.
data class Elev(val nume: String, val clasa: String, val medie: Double)
fun main() {
val temperaturi = mapOf("Iași" to 14, "Cluj" to 11, "Constanța" to 17)
for ((oras, grade) in temperaturi) println("$oras: $grade °C")
val elevi = listOf(Elev("Ana", "X B", 9.5), Elev("Radu", "X A", 8.25))
elevi.forEach { (nume, _, medie) -> println("$nume -> $medie") }
}
Rezultat
Iași: 14 °C
Cluj: 11 °C
Constanța: 17 °C
Ana -> 9.5
Radu -> 8.25
Exemplul 3: componentN pentru o clasă proprie
Clasa Interval nu este data, dar definește component1 și component2 cu operator, deci poate fi desfăcută.
class Interval(val start: Int, val sfarsit: Int) {
operator fun component1() = start
operator fun component2() = sfarsit
}
fun main() {
val program = Interval(9, 17)
val (deschide, inchide) = program
println("Magazinul este deschis între $deschide și $inchide (${inchide - deschide} ore)")
val (primul, alDoilea) = listOf("aur", "argint", "bronz")
println("Locul 1: $primul, locul 2: $alDoilea")
}
Rezultat
Magazinul este deschis între 9 și 17 (8 ore)
Locul 1: aur, locul 2: argint
Greșeli frecvente
- Schimbarea ordinii proprietăților într-o
data class: toate destructurările existente primesc alte valori, fără nicio eroare de compilare dacă tipurile se potrivesc. - Destructuring pe o clasă obișnuită fără
componentN: eroaredestructuring of type 'X' requires operator function 'component1()'. - Uitarea parantezelor în lambda:
{ nume, nota -> }înseamnă doi parametri separați, nu unPairdesfăcut; se scrie{ (nume, nota) -> }.
Comenzi înrudite
data class: data class este o clasă pentru date: primește automat toString, equals, hashCode, copy și componentN.Pair: O pereche de două valori, first și second; a to b este felul scurt de a crea un Pair, folosit în mapOf.for: Parcurge pe rând elementele unei colecții, ale unui interval sau ale oricărui obiect care are iterator().operator: operator marchează o funcție cu nume special (plus, get, contains, compareTo…) ca să poată fi folosită prin +, [], in sau <.lambda: O lambda este o funcție fără nume, scrisă între acolade, pe care o poți pune într-o variabilă sau trimite altei funcții.