Property adalah cara Kotlin merepresentasikan data milik object. Berbeda dengan Java yang memisahkan field dan method getter/setter, Kotlin menyatukan keduanya menjadi satu konsep bernama property. Dari sisi pemanggil, akses buku.harga terlihat seperti akses field langsung, namun di balik layar kompilator dapat memanggil getter atau setter yang kita sesuaikan. Pada chapter ini kita akan membedah property var dan val, memperkenalkan backing field dengan keyword field, dan membuka jalan untuk lateinit var yang ditujukan untuk property non-null yang diisi belakangan.

Property var dan val #

Property dideklarasikan dengan dua keyword: var untuk property mutable dan val untuk property read-only. Property val hanya dapat ditugaskan satu kali, biasanya saat inisialisasi. Property var dapat ditugaskan ulang berkali-kali. Kedua jenis property wajib diinisialisasi saat deklarasi atau di dalam constructor, kecuali bila menggunakan modifier khusus seperti lateinit.

kotlin Contoh: property var dan val
class Buku(val judul: String, var harga: Int)

Pada contoh di atas, judul bersifat read-only dan harga bersifat mutable. Pemanggil dapat membaca buku.judul tetapi tidak dapat menugaskannya ulang, sedangkan buku.harga = 80000 diizinkan.

Backing Field dan Keyword field #

Setiap property Kotlin memiliki penyimpanan internal yang disebut backing field. Field ini hanya dapat diakses dari dalam custom accessor melalui keyword field. Saat kita menulis var harga: Int = 0, kompilator membuat field internal serta getter dan setter default yang membaca dan menulis field tersebut.

Custom setter memungkinkan kita memvalidasi setiap penugasan. Karena keyword field merujuk ke penyimpanan internal, kita harus menulis field = value (bukan harga = value) untuk menghindari pemanggilan setter secara rekursif yang akan menyebabkan galat stack overflow.

Contoh Property dengan Custom Accessor #

Contoh berikut mendemonstrasikan property var dengan custom setter yang menolak nilai negatif, property var dengan custom getter yang memberikan nilai default, serta property lateinit var yang diisi setelah object dibuat.

kotlin
// properties.kt
// Mendemonstrasikan property var, val, late-init, dan backing field sederhana.

class Buku(judul: String, hargaAwal: Int) {
    val judul: String = judul
    var harga: Int = hargaAwal
        set(value) {
            if (value >= 0) {
                field = value
            }
        }

    var jumlahHalaman: Int = 0
        get() = if (field > 0) field else 1
}

class Layar {
    lateinit var judul: String

    fun siapTampil(): Boolean = ::judul.isInitialized
}

fun main() {
    val buku = Buku("Belajar Kotlin", 75000)
    println("Judul: ${buku.judul}")
    println("Harga awal: ${buku.harga}")

    buku.harga = -5000
    println("Setelah set -5000: ${buku.harga}")

    buku.harga = 80000
    println("Setelah set 80000: ${buku.harga}")

    buku.jumlahHalaman = 0
    println("Halaman (field=0): ${buku.jumlahHalaman}")

    buku.jumlahHalaman = 120
    println("Halaman (field=120): ${buku.jumlahHalaman}")

    val layar = Layar()
    println("Layar judul terisi? ${layar.siapTampil()}")

    layar.judul = "Dashboard Penjualan"
    println("Layar judul terisi? ${layar.siapTampil()}")
    println("Judul layar: ${layar.judul}")
}

Output yang Dihasilkan:

text
Judul: Belajar Kotlin
Harga awal: 75000
Setelah set -5000: 75000
Setelah set 80000: 80000
Halaman (field=0): 1
Halaman (field=120): 120
Layar judul terisi? false
Layar judul terisi? true
Judul layar: Dashboard Penjualan

Mari kita amati peran tiap bagian:

  1. val judul: String = judul: property read-only. Nilai ditugaskan satu kali saat inisialisasi dan tidak dapat diubah lagi.
  2. var harga: Int = hargaAwal dengan custom setter: saat pemanggil menulis buku.harga = -5000, setter memeriksa kondisi value >= 0. Karena -5000 tidak memenuhi kondisi, penugasan ke field tidak terjadi dan nilai harga tetap 75000.
  3. field = value: keyword field merujuk ke penyimpanan internal property. Bila kita menulis harga = value di dalam setter, kompilator akan memanggil setter yang sama lagi tanpa henti — ini adalah jebakan umum yang harus dihindari.
  4. var jumlahHalaman: Int = 0 dengan custom getter get() = if (field > 0) field else 1: saat field bernilai 0, getter mengembalikan 1 sebagai default. Saat field bernilai 120, getter mengembalikan 120 apa adanya. Nilai default ini tidak mengubah field internal.
  5. lateinit var judul: String: modifier lateinit memberi tahu kompilator bahwa property akan diisi belakangan. Sebelum diisi, property tidak boleh dibaca.
  6. ::judul.isInitialized: ekspresi ini memeriksa apakah property lateinit sudah diberi nilai. Berguna untuk menghindari UninitializedPropertyAccessException saat runtime.

Property val Tidak Memiliki Setter #

Property val hanya boleh memiliki custom getter, tidak boleh memiliki setter. Hal ini konsisten dengan sifat read-only: nilai hanya ditentukan satu kali saat inisialisasi dan tidak dapat diubah. Bila sebuah val ingin mengembalikan nilai hasil komputasi, kita cukup menulis custom getter tanpa menyentuh field. Contoh: val pajak: Int get() = harga / 10.

Modifier lateinit #

Modifier lateinit dirancang untuk property var bertipe non-primitif (biasanya object) yang akan diisi setelah object dibuat — misalnya pada framework yang memerlukan injeksi dependensi atau pada pengujian dengan setup terpisah. Tiga batasan penting: hanya boleh var (bukan val), tidak boleh bertipe primitif (Int, Boolean, dll.), dan tidak boleh memiliki custom getter atau setter.

Referensi Lanjutan #

  • Properties — panduan resmi deklarasi property val, var, dan lateinit

Ringkasan Property #

Property Kotlin menyatukan field dan accessor dalam satu deklarasi. Keyword val menandakan read-only, var menandakan mutable. Custom accessor dengan keyword field memberi kontrol penuh atas pembacaan dan penugasan tanpa kehilangan struktur internal. Modifier lateinit memungkinkan penundaan inisialisasi property non-null. Pada chapter Primary Constructor berikutnya, kita akan melihat bagaimana property dideklarasikan langsung pada daftar parameter constructor untuk membuat class yang ringkas namun ekspresif.