Salah satu kemudahan utama Kotlin dibandingkan Java adalah kita dapat menulis function, property, dan class langsung pada level file tanpa membungkusnya dalam class pembungkus. Hal ini disebut file-level declaration atau top-level declaration. Pada chapter ini kita akan memahami apa saja yang dapat dideklarasikan di top-level, konvensi penamaan file, dan bagaimana kompilator mengelola deklarasi tersebut pada bytecode JVM.
Apa yang Bisa Dideklarasikan di Top-Level #
Kotlin mengizinkan beberapa jenis deklarasi pada level file:
| Jenis | Contoh | Keterangan |
|---|---|---|
| Function | fun hitungPajak(...) | Sering dipakai untuk utility dan helper. |
| Property | val NAMA_APLIKASI = "..." | Konstanta atau nilai konfigurasi global. |
| Mutable property | var jumlahTransaksi = 0 | Hati-hati: shared state. |
| Class / Interface | class Transaksi(...) | Setara dengan class Java, tapi tanpa paksaan satu class per file. |
| Object | object BukuBesar { ... } | Singleton top-level. |
| Type alias | typealias DaftarTugas = List<Tugas> | Memberi nama alternatif untuk tipe. |
| Extension function | fun String.hanyaAngka(): String | Memperluas tipe tanpa subclass. |
Contoh Kode #
Kode berikut memperlihatkan beragam deklarasi top-level dalam satu file:
// File: file_level_declarations.kt
// Mendemonstrasikan deklarasi top-level: function, property, class, dan constant.
package com.example.berkas
import kotlin.math.abs
// Top-level function — tidak perlu class pembungkus.
fun hitungPajak(nilai: Long, tarif: Double): Long {
val pajak = (nilai * tarif).toLong()
return pajak
}
// Top-level property — dapat diakses dari file lain dalam paket yang sama.
val NAMA_APLIKASI: String = "Kasir Sederhana"
// Top-level constant — nilai tetap di-inline pada saat kompilasi.
const val VERSI: String = "1.0.0"
// Top-level mutable property — gunakan dengan hati-hati.
var jumlahTransaksi: Int = 0
// Top-level class.
data class Transaksi(val id: Long, val nominal: Long, val keterangan: String)
// Top-level object singleton.
object BukuBesar {
private val daftar: MutableList<Transaksi> = mutableListOf()
fun catat(transaksi: Transaksi) {
daftar.add(transaksi)
jumlahTransaksi += 1
}
fun total(): Long = daftar.sumOf { it.nominal }
}
fun main() {
val t1 = Transaksi(id = 1L, nominal = 50_000L, keterangan = "penjualan buku")
val t2 = Transaksi(id = 2L, nominal = 75_000L, keterangan = "penjualan pulpen")
BukuBesar.catat(t1)
BukuBesar.catat(t2)
println("$NAMA_APLIKASI v$VERSI")
println("Jumlah transaksi: $jumlahTransaksi")
println("Total nominal: ${BukuBesar.total()}")
println("Pajak atas total: ${hitungPajak(BukuBesar.total(), 0.11)}")
println("Absolut selisih: ${abs(t1.nominal - t2.nominal)}")
}Output yang Dihasilkan:
Kasir Sederhana v1.0.0
Jumlah transaksi: 2
Total nominal: 125000
Pajak atas total: 13750
Absolut selisih: 25000Mari kita bedah baris-baris di atas:
- Baris 3 (
package com.example.berkas): deklarasi package. Semua deklarasi top-level berikutnya akan berada di ruang nama ini. - Baris 8 (
fun hitungPajak(...)): function top-level. Pada JVM, function ini akan dikompilasi menjadi static method pada classFileLevelDeclarationsKt(nama class otomatis dari nama file). - Baris 14 (
val NAMA_APLIKASI): property read-only top-level. Pada JVM menjadi static getter pada classFileLevelDeclarationsKt. - Baris 17 (
const val VERSI): konstanta compile-time. Karenaconst, nilainya di-inline pada setiap titik pemakaian; tidak ada getter runtime. - Baris 20 (
var jumlahTransaksi): property mutable top-level. Mutable global state harus dipakai dengan hati-hati karena dapat membingungkan pada kode multi-thread. - Baris 23 (
data class Transaksi): class top-level. Menghasilkanequals,hashCode,toString, dancopyotomatis. - Baris 26-34 (
object BukuBesar): singleton top-level. Kompilator memastikan hanya ada satu instance. - Baris 36-46 (
fun main): titik masuk program. Memanggil semua deklarasi di atas.
Konvensi Nama File #
Nama file .kt bebas — tidak harus sama dengan nama class. Namun konvensi yang dipakai ekosistem Kotlin adalah:
- Jika file berisi satu class utama, nama file mengikuti nama class (misalnya
Transaksi.ktberisiclass Transaksi). - Jika file berisi kumpulan function utilitas, gunakan nama deskriptif dalam PascalCase (misalnya
StringUtils.ktatauNumberUtils.kt). - File berisi extension function biasanya dinamai sesuai tipe yang diperluas, misalnya
StringExtensions.kt.
Mengapa Top-Level Berguna #
Deklarasi top-level membuat kode lebih ringkas karena kita tidak perlu membungkus utility function dalam class Util atau Helper seperti di Java. Hal ini juga membantu membaca: function hitungPajak cukup ditulis satu kali, tidak perlu berdebat apakah ditaruh di class PajakUtil atau class TaxHelper.
Referensi Lanjutan #
- Packages — bagian top-level declaration pada file Kotlin di panduan resmi
Selanjutnya #
Satu file saja kadang tidak cukup untuk proyek nyata. Chapter Multi-File Projects akan membahas bagaimana beberapa file .kt berbagi package dan saling memanggil.