class în Kotlin

Clase și obiecte Kotlin 1.0

class declară o clasă: un tip nou care grupează date (proprietăți) și comportament (metode).

Sintaxă
class Nume(val proprietate: Tip, var alta: Tip) {
    fun metoda() { ... }
}

val obiect = Nume(valoare, valoare)     // fără new

Ce face class

O clasă este un șablon după care creezi obiecte. În Kotlin, proprietățile se declară cel mai des direct în constructorul primar, din paranteza de după nume: class Produs(val nume: String, var pret: Double). val face proprietatea doar de citit, var o face modificabilă. Fără val/var, parametrul este doar un argument al constructorului, nu o proprietate.

Un obiect se creează apelând clasa ca pe o funcție, fără new: val caiet = Produs("Caiet", 7.5). Proprietățile și metodele se folosesc cu punct: caiet.pret, caiet.reducere(10). Corpul clasei (acoladele) poate lipsi dacă nu ai metode.

În Kotlin clasele sunt final implicit (nu pot fi moștenite fără open) și public. O clasă obișnuită nu are toString, equals sau copy utile; pentru clase care doar țin date folosește data class.

Exemple

Exemplul 1: Clasă cu proprietăți și metode

nume nu se poate schimba (val), pret da (var). Metoda aplicaReducere modifică obiectul.

class Produs(val nume: String, var pret: Double) {
    fun aplicaReducere(procent: Int) {
        pret = pret * (100 - procent) / 100
    }

    fun eticheta() = "$nume: $pret lei"
}

fun main() {
    val caiet = Produs("Caiet A4", 12.0)
    println(caiet.eticheta())
    caiet.aplicaReducere(25)
    println(caiet.eticheta())
    println("Doar numele: ${caiet.nume}")
}

Rezultat

Caiet A4: 12.0 lei
Caiet A4: 9.0 lei
Doar numele: Caiet A4

Exemplul 2: Stare privată și proprietate calculată

sold este privat, deci se schimbă doar prin metode care verifică regulile. esteGol este calculată la fiecare citire.

class ContBancar(val titular: String) {
    private var sold = 0

    val esteGol: Boolean get() = sold == 0

    fun depune(suma: Int) {
        require(suma > 0) { "Suma trebuie să fie pozitivă" }
        sold += suma
    }

    fun retrage(suma: Int): Boolean {
        if (suma > sold) return false
        sold -= suma
        return true
    }

    fun raport() = "$titular are $sold lei"
}

fun main() {
    val cont = ContBancar("Ana Popescu")
    println("Gol la început? ${cont.esteGol}")
    cont.depune(500)
    println("Retrag 200: ${cont.retrage(200)}")
    println("Retrag 1000: ${cont.retrage(1000)}")
    println(cont.raport())
}

Rezultat

Gol la început? true
Retrag 200: true
Retrag 1000: false
Ana Popescu are 300 lei

Exemplul 3: Două variabile, același obiect

Variabilele țin o referință la obiect. b = a nu copiază obiectul: schimbarea prin b se vede și prin a. === verifică dacă este același obiect.

class Elev(val nume: String, var nota: Int)

fun main() {
    val a = Elev("Mihai", 7)
    val b = a
    b.nota = 9
    println("a.nota = ${a.nota}")
    println("a și b sunt același obiect? ${a === b}")

    val c = Elev("Mihai", 9)
    println("a și c sunt același obiect? ${a === c}")
    println("a == c? ${a == c} (clasa obișnuită compară referințele)")
}

Rezultat

a.nota = 9
a și b sunt același obiect? true
a și c sunt același obiect? false
a == c? false (clasa obișnuită compară referințele)

Greșeli frecvente

  • Scrierea lui new Produs(...) ca în Java: în Kotlin new nu există.
  • Uitarea lui val/var în constructor: class Produs(nume: String) nu creează proprietatea, deci caiet.nume dă eroarea unresolved reference 'nume'.
  • Așteptarea ca println(obiect) să afișeze proprietățile: o clasă obișnuită afișează ceva de forma Produs@1b6d3586. Scrie toString() sau folosește data class.

Comenzi înrudite

  • constructor și init: constructor declară un constructor secundar (sau unul primar cu modificatori); blocurile init rulează la crearea fiecărui obiect.
  • data class: data class este o clasă pentru date: primește automat toString, equals, hashCode, copy și componentN.
  • this: this înseamnă obiectul curent: obiectul pe care s-a apelat metoda sau receptorul unei funcții de extensie.
  • 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.
  • open și final: În Kotlin clasele și metodele sunt final implicit; open permite moștenirea sau suprascrierea, iar final o oprește din nou.
  • object: object declară o clasă cu un singur obiect (singleton) sau creează pe loc un obiect anonim care implementează o interfață.