this în Kotlin

Clase și obiecte Kotlin 1.0

this înseamnă obiectul curent: obiectul pe care s-a apelat metoda sau receptorul unei funcții de extensie.

Sintaxă
this                 // obiectul curent (sau receptorul unei extensii)
this.proprietate
this@NumeClasa       // obiectul clasei exterioare / receptorul cu eticheta
constructor(...) : this(...)

Ce face this

În interiorul unei metode, this este obiectul pe care s-a apelat metoda. De obicei nu trebuie scris (pret înseamnă this.pret), dar devine necesar când un parametru are același nume ca proprietatea: this.pret = pret. Poți folosi this și ca să returnezi obiectul curent (pentru apeluri înlănțuite) sau ca să-l dai altei funcții.

Într-o funcție de extensie sau într-o lambda cu receptor (apply, with, buildString), this este receptorul. Când sunt mai multe niveluri, this se referă la cel mai apropiat; pentru unul exterior folosești o etichetă: this@Comanda (numele clasei) sau this@apply (numele funcției).

În constructori, this(...) apelează alt constructor al aceleiași clase.

Exemple

Exemplul 1: Parametru cu același nume ca proprietatea

În schimbaPret, pret este parametrul, iar this.pret este proprietatea obiectului.

class Produs(val nume: String, var pret: Int) {
    fun schimbaPret(pret: Int) {
        println("Prețul pentru $nume se schimbă din ${this.pret} în $pret")
        this.pret = pret
    }
}

fun main() {
    val lapte = Produs("Lapte", 8)
    lapte.schimbaPret(9)
    println("Preț nou: ${lapte.pret} lei")
}

Rezultat

Prețul pentru Lapte se schimbă din 8 în 9
Preț nou: 9 lei

Exemplul 2: return this pentru apeluri înlănțuite

Fiecare metodă returnează obiectul curent, deci apelurile se pot scrie unul după altul.

class Mesaj {
    private val parti = mutableListOf<String>()
    fun catre(nume: String): Mesaj { parti.add("Către: $nume"); return this }
    fun subiect(text: String): Mesaj { parti.add("Subiect: $text"); return this }
    fun text(t: String): Mesaj { parti.add(t); return this }
    fun construieste() = parti.joinToString("\n")
}

fun main() {
    val email = Mesaj()
        .catre("ana@exemplu.ro")
        .subiect("Ședința de luni")
        .text("Ne vedem la ora 10, în sala 2.")
        .construieste()
    println(email)
}

Rezultat

Către: ana@exemplu.ro
Subiect: Ședința de luni
Ne vedem la ora 10, în sala 2.

Exemplul 3: this cu etichetă

În apply, this este StringBuilder-ul. this@Comanda ajunge la obiectul clasei exterioare.

class Comanda(val numar: Int, val produse: List<String>) {
    fun rezumat(): String = StringBuilder().apply {
        append("Comanda ")
        append(this@Comanda.numar)
        append(": ")
        append(produse.joinToString())
        append(" (${this.length} caractere până aici)")
    }.toString()
}

fun main() {
    println(Comanda(1024, listOf("pâine", "brânză")).rezumat())
}

Rezultat

Comanda 1024: pâine, brânză (27 caractere până aici)

Greșeli frecvente

  • Scrierea pret = pret când parametrul are același nume: atribui parametrul lui însuși (eroare, parametrii sunt val). Scrie this.pret = pret.
  • În lambda-urile cu receptor, this nu mai este obiectul clasei: în apply { } este obiectul pe care s-a apelat apply. Folosește this@NumeClasa.
  • this într-o funcție de nivel de sus fără receptor: nu există obiect curent, deci este eroare.

Comenzi înrudite

  • class: class declară o clasă: un tip nou care grupează date (proprietăți) și comportament (metode).
  • Funcții de extensie: O funcție de extensie adaugă o metodă nouă unui tip existent (String, Int, List), fără să modifici clasa.
  • apply: Configurează un obiect într-un bloc în care obiectul este this, apoi returnează chiar obiectul.
  • inner class: inner marchează o clasă din interiorul alteia care ține o referință la obiectul exterior și îi poate folosi membrii.
  • constructor și init: constructor declară un constructor secundar (sau unul primar cu modificatori); blocurile init rulează la crearea fiecărui obiect.