Tipe data sederhana seperti arah mata angin, status pesan, dan tingkat prioritas sering hanya memiliki nilai tetap yang sudah diketahui di awal. Java dan Kotlin menyediakan enum untuk merepresentasikan nilai-nilai tersebut dengan tipe yang aman — setiap nilai adalah instance dari class enum, bukan string bebas atau angka magic. Kotlin enum class lebih kaya daripada Java: ia dapat memiliki property, constructor, method, dan bahkan mengimplementasikan interface. Pada chapter ini kita akan mendeklarasikan enum dengan property, menambah method yang memanfaatkan when, dan mengimplementasikan interface pada setiap konstanta enum.

Apa Itu enum class #

enum class adalah class khusus yang instance-nya terbatas pada daftar konstanta yang dideklarasikan di dalamnya. Setiap konstanta adalah instance tunggal dari class enum tersebut — Kotlin menjamin hanya instance yang terdaftar yang ada selama aplikasi berjalan. Karena instance bersifat tunggal, pembandingan dengan == antara dua konstanta enum hanya membandingkan referensi yang sama, sehingga efisien dan aman.

Berbeda dari Java, Kotlin enum class dapat memiliki:

  • Property dengan constructor — setiap konstanta dapat menyimpan nilai property.
  • Method di body class — method dapat memanfaatkan when(this) untuk mengembalikan nilai spesifik per konstanta.
  • Implementasi interface — setiap konstanta dapat mengimplementasikan method interface dengan body yang berbeda.
  • Override method abstrak di setiap konstanta — body yang berbeda untuk tiap konstanta.

Enum dengan Property dan Method #

Contoh berikut mendefinisikan empat enum: Arah dengan property simbol: Char dan method lawan() serta derajat(), StatusPesan sederhana dengan method predikat, Tingkat dengan property nilai: Int yang mengimplementasikan Comparable, dan ModeTransportasi yang mengimplementasikan interface DapatDijelaskan dengan body berbeda di setiap konstanta.

kotlin
// enum_classes.kt
// Mendemonstrasikan `enum class` Kotlin — constants, properties, methods,
// constructor, interface implementation.

enum class Arah(val simbol: Char) {
    UTARA('↑'),
    SELATAN('↓'),
    TIMUR('→'),
    BARAT('←');

    fun lawan(): Arah = when (this) {
        UTARA -> SELATAN
        SELATAN -> UTARA
        TIMUR -> BARAT
        BARAT -> TIMUR
    }

    fun derajat(): Int = when (this) {
        UTARA -> 0
        TIMUR -> 90
        SELATAN -> 180
        BARAT -> 270
    }
}

enum class StatusPesan {
    DRAF,
    TERKIRIM,
    DIBACA,
    DIARSIPKAN;

    fun dapatDihapus(): Boolean = this == DRAF || this == DIARSIPKAN
}

enum class Tingkat(val nilai: Int) : Comparable<Tingkat> {
    RENDAH(1),
    SEDANG(2),
    TINGGI(3),
    DARURAT(4);

    fun lebihTinggiDari(lain: Tingkat): Boolean = this.nilai > lain.nilai
}

// Enum yang mengimplementasikan interface.
interface DapatDijelaskan {
    fun jelaskan(): String
}

enum class ModeTransportasi : DapatDijelaskan {
    JALAN_KAKI {
        override fun jelaskan(): String = "berjalan kaki — kecepatan 5 km/jam"
    },
    SEPEDA {
        override fun jelaskan(): String = "bersepeda — kecepatan 15 km/jam"
    },
    MOBIL {
        override fun jelaskan(): String = "berkendara mobil — kecepatan 60 km/jam"
    }
}

fun main() {
    println("Daftar Arah:")
    for (arah in Arah.entries) {
        println("  ${arah.name} ${arah.simbol} — ${arah.derajat()} derajat, lawan: ${arah.lawan()}")
    }
    println()

    val dipilih = Arah.TIMUR
    println("Dipilih: ${dipilih.name} (${dipilih.simbol})")
    println("Lawan arah: ${dipilih.lawan()}")
    println("ordinal: ${dipilih.ordinal}")
    println()

    println("Status pesan:")
    val daftarStatus = listOf(StatusPesan.DRAF, StatusPesan.TERKIRIM, StatusPesan.DIBACA, StatusPesan.DIARSIPKAN)
    for (s in daftarStatus) {
        println("  ${s.name} — dapat dihapus: ${s.dapatDihapus()}")
    }
    println()

    println("Perbandingan Tingkat:")
    val a = Tingkat.SEDANG
    val b = Tingkat.DARURAT
    println("  a=$a (${a.nilai}), b=$b (${b.nilai})")
    println("  a > b ? ${a.lebihTinggiDari(b)}")
    println("  b > a ? ${b.lebihTinggiDari(a)}")
    println("  a compareTo b = ${a.compareTo(b)}")
    println()

    println("Mode transportasi:")
    for (mode in ModeTransportasi.entries) {
        println("  ${mode.name} -> ${mode.jelaskan()}")
    }
}

Output yang Dihasilkan:

text
Daftar Arah:
  UTARA ↑ — 0 derajat, lawan: SELATAN
  SELATAN ↓ — 180 derajat, lawan: UTARA
  TIMUR → — 90 derajat, lawan: BARAT
  BARAT ← — 270 derajat, lawan: TIMUR

Dipilih: TIMUR (→)
Lawan arah: BARAT
ordinal: 2

Status pesan:
  DRAF — dapat dihapus: true
  TERKIRIM — dapat dihapus: false
  DIBACA — dapat dihapus: false
  DIARSIPKAN — dapat dihapus: true

Perbandingan Tingkat:
  a=SEDANG (2), b=DARURAT (4)
  a > b ? false
  b > a ? true
  a compareTo b = -2

Mode transportasi:
  JALAN_KAKI -> berjalan kaki — kecepatan 5 km/jam
  SEPEDA -> bersepeda — kecepatan 15 km/jam
  MOBIL -> berkendara mobil — kecepatan 60 km/jam

Mari kita bedah kode di atas:

  1. enum class Arah(val simbol: Char) { UTARA('↑'), ... }: enum dengan property simbol di constructor. Setiap konstanta memberi nilai simbol saat deklarasi — UTARA('↑'), TIMUR('→'). Setelah konstanta terakhir, tanda ; wajib dipakai bila ada deklarasi method di bawahnya.
  2. fun lawan(): Arah = when (this) { UTARA -> SELATAN; ... }: method enum memakai when(this) untuk mengembalikan nilai spesifik per konstanta. when pada enum bersifat exhaustive — bila ada konstanta yang belum ditangani, kompilator memberi peringatan atau error.
  3. for (arah in Arah.entries): properti entries (Kotlin 1.9+) mengembalikan daftar semua konstanta enum. Sebelumnya properti ini bernama values() yang kini sudah deprecated. Property bawaan enum lain: name (nama konstanta sebagai string), ordinal (indeks posisi konstanta).
  4. dipilih.name, dipilih.simbol, dipilih.ordinal: tiga property bawaan enum. name adalah nama konstanta sebagai string ("TIMUR"), simbol adalah property yang dideklarasikan di constructor ('→'), dan ordinal adalah indeks posisi konstanta dalam deklarasi (2 untuk TIMUR).
  5. enum class StatusPesan { DRAF, ...; fun dapatDihapus(): Boolean = this == DRAF || this == DIARSIPKAN }: enum tanpa property constructor. Method memanfaatkan operator == yang aman dan efisien untuk enum karena membandingkan referensi instance tunggal.
  6. enum class Tingkat(val nilai: Int) : Comparable<Tingkat>: enum dapat mengimplementasikan interface. Implementasi Comparable<Tingkat> memberi method compareTo otomatis — output a compareTo b = -2 menunjukkan SEDANG kurang dari DARURAT selisih 2 (4 - 2 = 2).
  7. enum class ModeTransportasi : DapatDijelaskan { JALAN_KAKI { override fun jelaskan() = ... }, ... }: setiap konstanta dapat memiliki body sendiri yang mengoverride method abstrak dari interface. Body konstanta dipisahkan dengan tanda , seperti konstanta biasa, namun setelahnya wajib diakhiri ; bila ada deklarasi lain. Output menunjukkan setiap konstanta mengembalikan string yang berbeda dari jelaskan().

Enum dan when #

Kombinasi enum dan when adalah pola yang sering muncul di kode Kotlin. when pada enum bersifat exhaustive — kompilator memverifikasi bahwa semua konstanta telah ditangani. Bila kita menambah konstanta baru ke enum, semua when yang memproses enum tersebut akan ditandai sebagai tidak lengkap, memaksa kita memperbarui kode. Sifat ini membuat enum lebih aman daripada string atau angka magic untuk merepresentasikan nilai diskret.

Enum dengan Body Konstanta #

Ketika sebuah interface memiliki banyak method dan implementasi tiap konstanta cukup berbeda, kita dapat mendefinisikan body konstanta — blok kode setelah nama konstanta yang mengoverride method abstrak. ModeTransportasi di atas menggunakan pola ini: setiap konstanta (JALAN_KAKI, SEPEDA, MOBIL) mengoverride method jelaskan() dengan body yang spesifik. Body konstanta dapat juga menyimpan property tambahan, namun property tersebut hanya dapat diakses dari dalam konstanta itu sendiri.

Referensi Lanjutan #

  • Enum classes — panduan resmi enum class beserta constructor dan konstanta

Ringkasan #

enum class Kotlin dapat memiliki property, constructor, method, dan implementasi interface — lebih ekspresif daripada enum Java. Kombinasi enum dengan when memberikan keamanan exhaustiveness yang memaksa pembaruan kode saat konstanta baru ditambahkan. Property name, ordinal, dan entries adalah cara utama mengakses metadata enum. Pada chapter sealed class berikutnya, kita akan melihat alternatif enum untuk hierarki yang lebih kompleks — class dengan subtype terbatas yang dapat menyimpan state.