enum class în Kotlin

Clase și obiecte Kotlin 1.0 (entries: Kotlin 1.9)

enum class declară un tip cu un număr fix de valori numite (zilele săptămânii, stările unei comenzi).

Sintaxă
enum class Nume { A, B, C }

enum class Nume(val proprietate: Tip) {
    A(valoare), B(valoare);
    fun metoda() = ...
}

Nume.entries        Nume.valueOf("A")        A.name        A.ordinal

Ce face enum class

O clasă enum are un set fix de valori, scrise în corp: enum class Anotimp { PRIMAVARA, VARA, TOAMNA, IARNA }. O variabilă de tipul Anotimp poate avea doar una dintre aceste valori, nu un text oarecare, deci greșelile de scriere sunt prinse la compilare.

Fiecare valoare are name (numele ca text) și ordinal (poziția, de la 0). Anotimp.entries (Kotlin 1.9+) dă lista tuturor valorilor, iar Anotimp.valueOf("VARA") găsește valoarea după nume (aruncă IllegalArgumentException dacă numele nu există). Valorile pot avea proprietăți (din constructor) și metode; după ultima valoare se pune ; înaintea membrilor.

when pe o valoare enum este exhaustiv: dacă tratezi toate valorile, nu ai nevoie de else, iar dacă adaugi o valoare nouă, compilatorul îți arată unde ai uitat-o.

Exemple

Exemplul 1: Enum simplu, entries și when

when tratează toate cele patru valori, deci nu are else. entries parcurge valorile în ordinea declarării.

enum class Anotimp { PRIMAVARA, VARA, TOAMNA, IARNA }

fun activitate(a: Anotimp) = when (a) {
    Anotimp.PRIMAVARA -> "plantăm flori"
    Anotimp.VARA -> "mergem la mare"
    Anotimp.TOAMNA -> "culegem struguri"
    Anotimp.IARNA -> "facem om de zăpadă"
}

fun main() {
    for (a in Anotimp.entries) {
        println("${a.ordinal} ${a.name}: ${activitate(a)}")
    }
    val ales = Anotimp.valueOf("VARA")
    println("Ales: $ales")
}

Rezultat

0 PRIMAVARA: plantăm flori
1 VARA: mergem la mare
2 TOAMNA: culegem struguri
3 IARNA: facem om de zăpadă
Ales: VARA

Exemplul 2: Enum cu proprietăți și metode

Fiecare stare a comenzii are un text și un număr de zile. Metoda urmatoarea folosește ordinal și entries.

enum class StareComanda(val text: String, val zile: Int) {
    PLASATA("Comandă plasată", 0),
    PREGATITA("În pregătire", 1),
    EXPEDIATA("Predată curierului", 2),
    LIVRATA("Livrată", 4);

    fun urmatoarea(): StareComanda? = entries.getOrNull(ordinal + 1)
}

fun main() {
    var stare: StareComanda? = StareComanda.PLASATA
    while (stare != null) {
        println("Ziua ${stare.zile}: ${stare.text}")
        stare = stare.urmatoarea()
    }
}

Rezultat

Ziua 0: Comandă plasată
Ziua 1: În pregătire
Ziua 2: Predată curierului
Ziua 4: Livrată

Exemplul 3: valueOf cu nume greșit și comparare

Valorile enum se compară după ordinea declarării. valueOf cu un nume inexistent aruncă excepție; entries.find este varianta sigură.

enum class Marime { S, M, L, XL }

fun main() {
    println("M < XL? ${Marime.M < Marime.XL}")
    println("Cea mai mare: ${Marime.entries.max()}")

    try {
        Marime.valueOf("XXL")
    } catch (e: IllegalArgumentException) {
        println("Eroare: ${e.message}")
    }
    println(Marime.entries.find { it.name == "XXL" } ?: "mărime necunoscută")
}

Rezultat

M < XL? true
Cea mai mare: XL
Eroare: No enum constant Marime.XXL
mărime necunoscută

Greșeli frecvente

  • Uitarea lui ; după ultima valoare când enum-ul are metode: eroare de sintaxă.
  • Folosirea lui values() în cod nou: funcționează, dar creează un tablou nou la fiecare apel. Din Kotlin 1.9 folosește entries.
  • Salvarea lui ordinal în baza de date: dacă reordonezi sau inserezi valori, numerele se schimbă. Salvează name sau un cod propriu.

Comenzi înrudite

  • when: Alege o ramură după valoarea unei expresii sau după prima condiție adevărată; înlocuiește switch din alte limbaje.
  • sealed class și sealed interface: sealed declară o ierarhie închisă: toate subtipurile sunt cunoscute la compilare, deci when le poate verifica pe toate fără else.
  • class: class declară o clasă: un tip nou care grupează date (proprietăți) și comportament (metode).
  • data class: data class este o clasă pentru date: primește automat toString, equals, hashCode, copy și componentN.