Ce face run
obiect.run { ... } rulează blocul cu obiectul ca this: în interior îi poți folosi direct proprietățile și metodele, fără să scrii numele obiectului. Rezultatul este ultima expresie din bloc, ca la let.
with(obiect) { ... } este aceeași idee, scrisă altfel: obiectul este argument, nu stă înaintea punctului. Se citește „cu obiectul ăsta, fă…” și este folosit când ai mai multe operații pe același obiect. Spre deosebire de run, nu poate fi folosit cu ?..
Există și run { ... } fără obiect: rulează pur și simplu blocul și îi returnează rezultatul. Este util pentru a calcula o valoare în câțiva pași, cu variabile care nu „scapă” în afara blocului.
Parametri
| Parametru | Descriere |
|---|---|
block: T.() -> R |
Blocul de cod, în care this este obiectul. Ultima expresie este rezultatul. |
receiver: T |
Doar la with: obiectul pe care lucrează blocul. |
Ce returnează
Rezultatul blocului (ultima expresie).
Exemple
Exemplul 1: run și with pe același obiect
În ambele blocuri, nume, note și media() se referă la obiectul student, fără să-l mai numim.
class Student(val nume: String, val note: List<Int>) {
fun media() = note.average()
}
fun main() {
val ana = Student("Ana", listOf(9, 10, 8))
val raport = ana.run {
"$nume are ${note.size} note și media ${media()}"
}
println(raport)
val promovat = with(ana) {
println("Verific notele lui $nume...")
note.all { it >= 5 }
}
println("Promovat: $promovat")
}
Rezultat
Ana are 3 note și media 9.0
Verific notele lui Ana...
Promovat: true
Exemplul 2: run fără obiect pentru un calcul în pași
Variabilele pret și tva există doar în bloc; în afara lui rămâne doar rezultatul.
fun main() {
val total = run {
val pret = 250.0
val tva = pret * 0.19
pret + tva
}
println("Total cu TVA: $total lei")
}
Rezultat
Total cu TVA: 297.5 lei
Exemplul 3: ?.run pentru o valoare care poate lipsi
Ca la let, cu ?. blocul rulează doar pentru valori diferite de null. Aici this este textul, deci length și uppercase() se aplică direct.
fun main() {
val orase: List<String?> = listOf("Iași", null, "Brașov")
for (oras in orase) {
val info = oras?.run { "${uppercase()} ($length litere)" } ?: "oraș necunoscut"
println(info)
}
}
Rezultat
IAȘI (4 litere)
oraș necunoscut
BRAȘOV (6 litere)
Greșeli frecvente
- Confunzi
runcuapply.runreturnează rezultatul blocului;applyreturnează obiectul. Dacă vrei obiectul configurat, foloseșteapply. - Scrii
with(x) { }cândxpoate fi null.withnu are variantă sigură; foloseștex?.run { }. - În bloc, un nume local cu același nume ca o proprietate o „ascunde”, iar codul folosește variabila locală fără să-ți dai seama. Evită numele care se suprapun.
Comenzi înrudite
let: Rulează un bloc de cod cu valoarea ca parametru it și returnează rezultatul blocului; des folosit cu ?. pentru valori null.apply: Configurează un obiect într-un bloc în care obiectul este this, apoi returnează chiar obiectul.also: Face o acțiune în plus cu un obiect (afișare, verificare, log) și returnează obiectul neschimbat.