Visibility modifier mengontrol siapa yang boleh mengakses sebuah deklarasi — class, property, method, atau top-level function. Kotlin memiliki empat modifier: public (default), private, protected, dan internal. Masing-masing memiliki aturan berbeda untuk deklarasi top-level versus anggota class. Pada chapter ini kita akan memetakan keempat modifier tersebut, melihat contoh konkret, dan memahami kapan masing-masing paling tepat dipakai.

Empat Modifier dan Aturannya #

Tabel berikut merangkum keempat modifier pada anggota class dan deklarasi top-level:

ModifierAnggota class (member)Top-level
public (default)Terlihat dari mana sajaTerlihat dari seluruh modul
privateHanya dalam class yang samaHanya dalam file yang sama
protectedHanya class dan subclass-nyaTidak dapat dipakai top-level
internalTerlihat dalam modul yang samaTerlihat dalam modul yang sama

Modul di sini berarti kumpulan file Kotlin yang dikompilasi bersama — misalnya satu modul Gradle, satu IntelliJ module, atau satu rangkaian file yang dikompilasi dengan satu pemanggilan kotlinc. Modifier internal berguna untuk membatasi API publik sebuah library tanpa membuat package terpisah.

public dan Default #

Semua deklarasi Kotlin bersifat public bila tidak ada modifier yang dituliskan. Artinya, property dan method class dapat diakses dari kode mana pun yang memiliki referensi ke object tersebut. Top-level function dapat dipanggil dari file lain dalam modul yang sama atau modul berbeda yang mengimpor pustaka tersebut.

kotlin Contoh: anggota public secara default
class Pengguna(val nama: String) {
    fun sapa() = "Halo, $nama"
}

Pada contoh di atas, property nama dan method sapa() keduanya public tanpa perlu menuliskan keyword tersebut. Konvensi Kotlin adalah menghilangkan public karena sudah menjadi default.

private pada Anggota dan Top-Level #

Modifier private pada anggota class membatasi akses hanya ke dalam class yang sama — termasuk ekstensi seperti inner class. Pada top-level, private membatasi akses hanya ke dalam file .kt yang sama. Pola ini sering dipakai untuk function helper atau konstanta yang tidak perlu terekspos ke file lain.

kotlin Contoh: private top-level dan member
private const val VERSI: Int = 1

class Layanan {
    private val token: String = "abc"
    fun tokenAktif(): Boolean = token.isNotEmpty()
}

Property token tidak dapat dibaca dari luar class Layanan. Konstanta VERSI hanya dapat dipakai di dalam file tempat deklarasinya berada — file lain di proyek yang sama tidak dapat mengaksesnya.

protected Hanya untuk Anggota #

Modifier protected tidak dapat dipakai pada deklarasi top-level — Kotlin melarang hal tersebut. protected hanya bermakna pada anggota class, dan aksesnya terbatas pada class itu sendiri serta subclass-nya. Karena subclass berada di luar class induk, protected sering dipakai untuk memberi subclass jalur internal tanpa membuka akses ke seluruh pemanggil.

kotlin Contoh: protected member
open class Hewan {
    protected val idInternal: Int = 42
}

class Kucing : Hewan() {
    fun ambilId(): Int = idInternal
}

Class Kucing dapat membaca idInternal karena menjadi subclass dari Hewan. Class lain yang bukan subclass tidak dapat mengaksesnya walaupun memiliki referensi ke object Hewan.

internal untuk Pembatasan Antar Modul #

Modifier internal membatasi visibilitas pada modul kompilasi yang sama. Modifier ini berguna untuk library yang ingin membagi function internal antar file tanpa mengeksposnya sebagai API publik. Bila sebuah library ingin menyembunyikan helper dari konsumen library tetapi memakainya di seluruh file library, internal adalah pilihan yang tepat.

Contoh Lengkap Empat Modifier #

Contoh berikut menggabungkan keempat modifier dalam satu program. Class Bank memiliki property private, internal, dan method public serta protected. Subclass BankAnak menunjukkan bahwa protected dan internal dapat diakses dari subclass, sementara top-level private const hanya tersedia di file yang sama.

kotlin
// visibility_modifiers.kt
// Mendemonstrasikan public, private, protected, internal pada class dan anggota.

// Catatan: `open` diperlukan agar Bank dapat diwariskan.
// Detail keyword `open` dibahas pada chapter open-classes-dan-methods.
open class Bank {
    private val kodeRahasia: String = "RAHASIA-2026"
    internal val namaCabang: String = "Cabang Pusat"

    fun infoPublik(): String {
        return "Bank $namaCabang, kode internal tercatat."
    }

    protected fun infoKode(): String {
        return "Kode: $kodeRahasia"
    }
}

class BankAnak : Bank() {
    fun laporanInternal(): String {
        // Bisa mengakses protected dan public, juga internal.
        return "${infoKode()} di $namaCabang"
    }
}

// Top-level deklarasi private
private const val VERSI_INTERNAL: Int = 1

fun versiSaatIni(): Int = VERSI_INTERNAL

fun main() {
    val b = Bank()
    println(b.infoPublik())
    println("Nama cabang (internal): ${b.namaCabang}")

    val anak = BankAnak()
    println(anak.laporanInternal())

    println("Versi modul: ${versiSaatIni()}")
}

Output yang Dihasilkan:

text
Bank Cabang Pusat, kode internal tercatat.
Nama cabang (internal): Cabang Pusat
Kode: RAHASIA-2026 di Cabang Pusat
Versi modul: 1

Mari kita amati perilakunya:

  1. private val kodeRahasia: hanya dapat diakses dari dalam class Bank. Method infoKode() membaca kodeRahasia karena berada di class yang sama; subclass BankAnak tidak dapat membaca kodeRahasia secara langsung, tetapi dapat memanggil method infoKode() yang protected.
  2. internal val namaCabang: dapat diakses dari seluruh file dalam modul yang sama. Karena program ini adalah satu modul, BankAnak.laporanInternal() dapat membaca namaCabang. Bila Bank dipublikasikan sebagai library terpisah, konsumen library tidak akan dapat mengakses namaCabang.
  3. fun infoPublik(): method public (default) dapat dipanggil dari main(). Method ini menyajikan ringkasan tanpa membocorkan kodeRahasia.
  4. protected fun infoKode(): hanya dapat dipanggil dari dalam class Bank dan subclass-nya. BankAnak.laporanInternal() dapat memanggil infoKode() karena menjadi subclass.
  5. private const val VERSI_INTERNAL: top-level private membatasi akses hanya pada file yang sama. Function versiSaatIni() berada dalam file yang sama sehingga dapat membacanya; file lain di modul yang sama tidak dapat.

Aturan Konstruksi yang Perlu Diingat #

Beberapa aturan penting:

  • Modifier default adalah public.
  • protected tidak dapat dipakai pada deklarasi top-level — hanya anggota class yang boleh.
  • Anggota private tidak diwariskan ke subclass.
  • Top-level private membatasi berdasarkan file .kt, bukan berdasarkan class.

Referensi Lanjutan #

Ringkasan #

Empat visibility modifier Kotlin memberi kontrol bertingkat atas akses deklarasi. public adalah default; private membatasi pada class atau file; protected membatasi pada class dan subclass; internal membatasi pada modul kompilasi yang sama. Pemilihan modifier yang tepat adalah fondasi encapsulation yang akan kita rangkum pada chapter Encapsulation berikutnya.