Setiap property Kotlin otomatis memiliki getter (untuk val dan var) dan setter (hanya untuk var). Saat kita menulis val x: Int = 5, kompilator menghasilkan getter default yang mengembalikan nilai field internal. Bila kita ingin mengubah perilaku pembacaan atau penugasan, Kotlin mengizinkan kita menulis custom accessor dengan sintaks ringkas. Pada chapter ini kita akan mempelajari custom getter, custom setter, dan computed property — property yang nilainya dihitung ulang setiap kali dibaca.

Custom Getter #

Custom getter ditulis dengan keyword get() di bawah deklarasi property. Setiap kali pemanggil membaca property, ekspresi di dalam getter dievaluasi. Computed property tidak memiliki backing field sendiri; nilainya dihitung berdasarkan property lain atau data eksternal.

kotlin Contoh: computed property tanpa backing field
class Lingkaran(var jariJari: Double) {
    val luas: Double
        get() = 3.14159 * jariJari * jariJari
}

Property luas tidak menyimpan nilai apa pun. Setiap kali c.luas dipanggil, ekspresi 3.14159 * jariJari * jariJari dievaluasi ulang dengan nilai jariJari saat itu. Bila jariJari berubah, luas otomatis mengikuti.

Custom Setter #

Custom setter ditulis dengan keyword set(nilai). Parameter setter (lazimnya value atau nama deskriptif) menerima nilai yang ditugaskan pemanggil. Di dalam setter, kita dapat memvalidasi, mengubah property lain, atau menghitung nilai balik sebelum disimpan.

kotlin Contoh: property dengan custom setter yang mengubah property lain
class Lingkaran(var jariJari: Double) {
    var keliling: Double
        get() = 2 * 3.14159 * jariJari
        set(nilai) {
            jariJari = nilai / (2 * 3.14159)
        }
}

Pemanggil c.keliling = 62.8318 tidak menyimpan 62.8318 ke field mana pun. Sebagai gantinya, setter menghitung jariJari = 62.8318 / (2 * 3.14159) = 10.0 dan menugaskannya ke property jariJari. Selanjutnya getter keliling akan mengembalikan nilai berdasarkan jariJari yang baru.

Contoh Lengkap dengan Tiga Accessor #

Contoh berikut memperlihatkan class Lingkaran dengan satu property biasa (jariJari), satu computed property (luas), dan dua property dengan getter+setter yang memanipulasi jariJari (keliling dan diameter). Setter diameter memuat validasi untuk memastikan nilai positif.

kotlin
// property_accessors.kt
// Mendemonstrasikan custom getter/setter dan computed property.

class Lingkaran(var jariJari: Double) {
    val luas: Double
        get() = 3.14159 * jariJari * jariJari

    var keliling: Double
        get() = 2 * 3.14159 * jariJari
        set(nilai) {
            jariJari = nilai / (2 * 3.14159)
        }

    var diameter: Double
        get() = 2 * jariJari
        set(nilai) {
            require(nilai > 0) { "Diameter harus positif" }
            jariJari = nilai / 2
        }
}

fun main() {
    val c = Lingkaran(5.0)
    println("Jari-jari: ${c.jariJari}")
    println("Luas: ${c.luas}")
    println("Keliling: ${c.keliling}")
    println("Diameter: ${c.diameter}")

    c.keliling = 62.8318
    println("Setelah set keliling=62.8318, jari-jari: ${c.jariJari}")

    c.diameter = 20.0
    println("Setelah set diameter=20.0, jari-jari: ${c.jariJari}")
    println("Luas akhir: ${c.luas}")
}

Output yang Dihasilkan:

text
Jari-jari: 5.0
Luas: 78.53975
Keliling: 31.4159
Diameter: 10.0
Setelah set keliling=62.8318, jari-jari: 10.0
Setelah set diameter=20.0, jari-jari: 10.0
Luas akhir: 314.159

Mari kita amati perilaku setiap accessor:

  1. val luas: Double get() = ...: computed property tanpa backing field. Setiap kali c.luas dipakai, ekspresi mengalikan jariJari saat itu dengan 3.14159.
  2. var keliling: Double dengan getter+setter: getter menghitung dari jariJari; setter menerima nilai baru, lalu mengubah jariJari agar konsisten. Tidak ada field keliling yang disimpan.
  3. c.keliling = 62.8318: pemanggilan setter dengan argumen 62.8318. Setter menghitung jariJari = 62.8318 / (2 * 3.14159) ≈ 10.0.
  4. c.diameter = 20.0: pemanggilan setter diameter dengan validasi require(nilai > 0). Setelah lolos, jariJari = 20.0 / 2 = 10.0. Bila pemanggil mencoba c.diameter = -5.0, IllegalArgumentException akan dilempar.
  5. c.luas di akhir: membaca property luas sekali lagi. Karena jariJari sekarang 10.0, hasilnya 3.14159 * 10 * 10 = 314.159. Perubahan jariJari otomatis tercermin pada luas.

Computed Property vs Method #

Computed property sering setara dengan method tanpa argumen. Pilihan antara keduanya adalah masalah gaya:

AspekComputed PropertyMethod
Sintaks pemanggilanc.luas (tanpa kurung)c.hitungLuas()
Komputasi ringan, tanpa efek sampingCocokBoleh
Komputasi berat atau I/OTidak disarankanLebih tepat
Mengikuti konvensi Java (mis. size())Tergantung preferensiLazim

Accessor dengan Backing Field #

Pada contoh diameter di atas, setter tidak menugaskan ke field melainkan ke property lain (jariJari). Bila kita ingin menyimpan nilai ke field internal sambil melakukan validasi, gunakan keyword field di dalam setter. Pembahasan mendalam tentang backing field akan menjadi fokus chapter Backing Fields berikutnya.

Referensi Lanjutan #

  • Properties — bagian getter dan setter custom pada panduan property

Ringkasan #

Custom accessor memberi kontrol penuh atas pembacaan dan penugasan property tanpa mengurangi kesederhanaan sintaks. Custom getter mengubah nilai yang dikembalikan; custom setter mengubah nilai yang ditugaskan. Computed property adalah property tanpa backing field yang dihitung ulang setiap pembacaan. Pada chapter Backing Fields berikutnya, kita akan menelaah lebih dalam keyword field dan batasannya dalam custom accessor.