val dan var

Immutability sebagai bawaan Kotlin, inferensi tipe, dan kapan var digunakan.

Daftar isi

Nilai pada Kotlin dideklarasikan dengan kata kunci val atau var. Perbedaan keduanya menentukan apakah nilai boleh diisi ulang, dan pilihan yang tepat membuat program lebih mudah dianalisis. Topik ini membahas cara mendeklarasikan keduanya, inferensi tipe yang menyertai deklarasi, serta aturan pengisian ulang yang ditegaskan compiler pada waktu kompilasi.

Penamaan variabel mengikuti gaya camelCase, yaitu huruf kecil pada kata pertama dan huruf kapital pada awal kata berikutnya, seperti tahunLahir dan rataRata. Nama yang dipilih sebaiknya menyatakan isiannya, misalnya umur daripada huruf tunggal seperti u, agar kode terbaca tanpa penjelasan tambahan.

Mendeklarasikan nilai dengan val#

Kata kunci val menyatakan nilai yang hanya boleh ditetapkan satu kali. Bentuk lengkap deklarasinya adalah val nama: Tipe = nilai, sedangkan bentuk singkat val nama = nilai meninggalkan penentuan tipe kepada kompilator. Setelah ditetapkan, nilai tersebut dipakai melalui namanya di seluruh bagian program.

Buat berkas nilai.kt berikut untuk melihat val menghitung umur dari tahun lahir.

kotlin nilai.kt
fun main() {
    val nama: String = "Citra"
    val tahunLahir = 2006
    val umur = 2026 - tahunLahir
    println("Nama: $nama")
    println("Umur: $umur tahun")
}
bash
# kompilasi nilai.kt dengan pustaka standar tersemat
kotlinc nilai.kt -include-runtime -d nilai.jar
# jalankan program
java -jar nilai.jar
text Keluaran
Nama: Citra
Umur: 20 tahun

Variabel umur tidak diisi dengan angka yang ditulis langsung, melainkan dengan ekspresi 2026 - tahunLahir. Kompilator mengevaluasi ekspresi tersebut menghasilkan 20, dan nilainya tidak berubah lagi selama program berjalan. Pola seperti ini adalah penggunaan val yang paling alami, yaitu menyimpan hasil perhitungan sekali lalu memakainya berulang kali.

Inferensi tipe#

Inferensi tipe (type inference) adalah kemampuan compiler menentukan tipe dari penginisialisasi tanpa pernyataan eksplisit. Kotlin menerapkannya secara konsisten, sehingga penulisan tipe pada variabel lokal bersifat opsional. Berkas inferensi.kt berikut membuktikan tipe yang dipilih kompilator dengan menampilkan nama kelasnya.

kotlin inferensi.kt
fun main() {
    val jumlah = 24
    val rataRata = 82.5
    val aktif = true
    val salam = "Halo"
    println(jumlah::class.simpleName)
    println(rataRata::class.simpleName)
    println(aktif::class.simpleName)
    println(salam::class.simpleName)
}
bash
# kompilasi inferensi.kt dengan pustaka standar tersemat
kotlinc inferensi.kt -include-runtime -d inferensi.jar
# jalankan program
java -jar inferensi.jar
text Keluaran
Int
Double
Boolean
String

Ekspresi jumlah::class.simpleName mengambil nama kelas dari tipe yang menyimpan nilai tersebut. Keluaran menunjukkan bahwa 24 diinferensi sebagai Int, 82.5 sebagai Double, true sebagai Boolean, dan "Halo" sebagai String. Tipe yang diinferensi tidak berbeda dengan tipe yang dinyatakan eksplisit, sehingga val jumlah = 24 dan val jumlah: Int = 24 menghasilkan program yang sama persis.

Tipe eksplisit tetap memiliki tempatnya meskipun inferensi tersedia. Penulisan tipe berguna ketika penginisialisasinya berupa pemanggilan fungsi yang tipenya tidak sekilas terlihat, atau ketika deklarasi itu dibaca tanpa konteks baris sekitarnya. Kompromi yang umum adalah mengandalkan inferensi untuk angka dan teks sederhana, lalu menuliskan tipe secara eksplisit ketika nilai asalnya tidak langsung terlihat.

Bentuk penetapan yang tertunda tersebut tetap tunduk pada aturan satu kali pengisian. Buat berkas tertunda.kt berikut.

kotlin tertunda.kt
fun main() {
    val label: String
    label = "tertunda"
    println("Isi: $label")
}
bash
# kompilasi tertunda.kt dengan pustaka standar tersemat
kotlinc tertunda.kt -include-runtime -d tertunda.jar
# jalankan program
java -jar tertunda.jar
text Keluaran
Isi: tertunda

Variabel label dideklarasikan dengan tipe eksplisit String tanpa nilai, lalu diisi satu kali pada pernyataan berikutnya. Kompilator menerima pola ini karena menjamin tidak ada pembacaan sebelum pengisian, dan pengisian kedua pada variabel yang sama tetap ditolak sebagaimana val pada umumnya.

Mengubah nilai dengan var#

Kata kunci var menyatakan variabel yang boleh diisi ulang. Deklarasi dan pengisiannya sama seperti val, tetapi pernyataan penugasan berikutnya tidak ditolak compiler. Berkas skor.kt berikut memperbarui skor dari 10 menjadi 24.

kotlin skor.kt
fun main() {
    var skor = 10
    println("Skor awal: $skor")
    skor = 24
    println("Skor setelah diperbarui: $skor")
}
bash
# kompilasi skor.kt dengan pustaka standar tersemat
kotlinc skor.kt -include-runtime -d skor.jar
# jalankan program
java -jar skor.jar
text Keluaran
Skor awal: 10
Skor setelah diperbarui: 24

Perintah skor = 24 mengganti isi variabel tanpa mendeklarasikannya ulang. Tipe variabel tetap terkunci sejak deklarasi, sehingga pengisian dengan nilai bertipe lain tetap ditolak. Tabel berikut merangkum perbedaan keduanya.

Aspekvalvar
Jumlah penugasansatu kaliberkali-kali
Pengubahan tipetidak dapattidak dapat
Status dalam programpilihan utamahanya bila nilai berubah

Ketika var dipakai, setiap pernyataan penugasan menjadi titik yang wajib dibaca oleh siapa pun yang menelusuri program, karena isi variabel setelah titik itu tidak lagi dapat dipastikan dari deklarasinya. Penulisan val menghapus titik-titik semacam itu, sehingga alur data menjadi lebih mudah diikuti. Perbedaan ini paling terasa pada program yang panjang, ketika satu variabel dipakai di banyak tempat.

Larangan mengisi ulang val#

Pengisian ulang val ditolak pada waktu kompilasi, bukan saat program berjalan. Berkas valerr.kt berikut sengaja melanggar aturan tersebut.

kotlin valerr.kt
fun main() {
    val batas = 100
    batas = 200
    println(batas)
}
bash
# kompilasi gagal karena val diisi ulang
kotlinc valerr.kt -d valerr.jar
text Keluaran
valerr.kt:3:5: error: 'val' cannot be reassigned.
    batas = 200
    ^^^^^

Pesan error menyebut posisi persisnya, yaitu baris 3 kolom 5 pada valerr.kt, dan penjelasannya 'val' cannot be reassigned. Perbaikannya mengikuti maksud program, yaitu menggunakan var bila nilai memang boleh berubah, atau mendeklarasikan val baru bila nilainya memang lain. Penolakan dini seperti inilah yang menjadikan val aman dipakai sebagai pilihan utama.

Aturan satu kali pengisian juga mengubah cara program dibaca. Ketika sebuah nilai bertanda val, seluruh penggunaannya di berkas tersebut dapat ditelusuri tanpa mencari penugasan lain, karena dipastikan tidak ada. Jaminan ini yang membuat pembacaan kode berbasis val lebih cepat, terutama pada berkas yang ditulis orang lain.

Ringkasan#

  • val menyatakan nilai yang ditetapkan satu kali, sedangkan var mengizinkan pengisian ulang dengan tipe yang tetap sama.
  • Inferensi tipe menentukan tipe variabel dari penginisialisasinya, sehingga penulisan tipe eksplisit pada variabel lokal bersifat opsional.
  • Pengisian ulang val ditolak compiler dengan pesan 'val' cannot be reassigned beserta posisi baris dan kolomnya.
  • var digunakan hanya bila nilai memang berubah, dan val menjadi pilihan utama untuk semua keadaan lain.

Referensi#