Kadang kita membutuhkan beberapa function penolong yang hanya relevan di dalam satu function induk. Mendeklarasikannya di level top-level akan mencemari namespace dan menyesatkan pembaca seolah-olah function tersebut siap dipakai di tempat lain. Kotlin menyediakan local functions — function yang dideklarasikan di dalam function lain. Pada chapter ini kita akan melihat bagaimana local function membantu mengurangi duplikasi tanpa mencemari scope luar.

Deklarasi Local Function #

Local function dideklarasikan dengan keyword fun di dalam body function induk. Local function dapat mengakses parameter dan variabel lokal dari function induk. Mekanisme ini disebut closure.

kotlin
fun ringkasanNilai(nilai: List<Int>): String {
    fun rataRata(): Double {
        var total = 0
        for (n in nilai) total += n
        return total.toDouble() / nilai.size
    }

    fun tertinggi(): Int {
        var maks = nilai[0]
        for (n in nilai) if (n > maks) maks = n
        return maks
    }

    fun terendah(): Int {
        var min = nilai[0]
        for (n in nilai) if (n < min) min = n
        return min
    }

    return "Rata-rata=${rataRata()}, Tertinggi=${tertinggi()}, Terendah=${terendah()}"
}

fun main() {
    val dataA = listOf(78, 85, 92, 67, 90)
    println("Kelas A: ${ringkasanNilai(dataA)}")

    val dataB = listOf(55, 60, 48, 72, 80, 65)
    println("Kelas B: ${ringkasanNilai(dataB)}")
}

Output yang Dihasilkan:

text
Kelas A: Rata-rata=82.4, Tertinggi=92, Terendah=67
Kelas B: Rata-rata=63.333333333333336, Tertinggi=80, Terendah=48

Mari kita bedah baris per baris:

  1. fun ringkasanNilai(nilai: List<Int>): String: function induk menerima daftar nilai. Body berisi tiga local function yang masing-masing menghitung rata-rata, nilai tertinggi, dan nilai terendah.
  2. fun rataRata(): Double: local function tanpa parameter, tetapi dapat membaca nilai dari function induk. Inilah inti closure — variabel luar tetap dapat diakses.
  3. fun tertinggi(): Int: local function lain yang juga membaca nilai. Tidak ada parameter eksplisit, sehingga pemanggilan tertinggi() terlihat sederhana.
  4. return "Rata-rata=${rataRata()}, ...": pemanggilan ketiga local function secara berurutan. Hasilnya digabungkan menjadi satu string ringkasan.

Manfaat Local Function #

Local function memberi tiga manfaat utama:

  • Visibility terbatas: local function tidak dapat dipanggil dari luar function induk. Pembaca tahu bahwa logika tersebut hanya dipakai di tempat ini.
  • DRY tanpa pencemaran namespace: kita dapat memecah function besar menjadi bagian-bagian kecil tanpa menambah method ke class atau top-level function ke file.
  • Closure: local function dapat membaca variabel dari function induk, sehingga tidak perlu meneruskan parameter berulang kali.
kotlin Contoh: local function menghindari duplikasi prefix
fun cetakLaporan(judul: String, item: List<String>) {
    fun baris(label: String, nilai: String) {
        println("| ${label.padEnd(15)} | ${nilai.padEnd(20)} |")
    }

    println("=== $judul ===")
    baris("Nama", "Nilai")
    baris("Total", item.size.toString())
    baris("Rata-rata", item.average().toString())
}

fun main() {
    cetakLaporan("Laporan Bulanan", listOf("90", "85", "70", "65"))
}

Tanpa local function baris, kita akan mengulang pola println("| ... | ... |") tiga kali. Dengan local function, pemanggilan menjadi seragam dan perubahan format cukup dilakukan di satu tempat.

Closure dan Mutasi Variabel #

Local function dapat membaca dan, bila variabel induk dideklarasikan dengan var, memodifikasi nilai variabel tersebut. Perilaku ini perlu dipakai dengan hati-hati karena mutasi dari local function dapat membuat alur kode sulit diikuti.

kotlin Contoh: local function yang memutasi variabel induk
fun akumulator(): () -> Int {
    var hitung = 0
    fun tambah(): Int {
        hitung += 1
        return hitung
    }
    return ::tambah
}

Function akumulator di atas mengembalikan function reference ::tambah yang menutup variabel hitung. Setiap pemanggilan hasil return akan menambah hitung dan mengembalikan nilai baru. Pola seperti ini sering dipakai untuk membuat generator atau iterator stateful.

Kapan Tidak Memakai Local Function #

Local function yang terlalu panjang atau dipanggil dari banyak tempat dalam function induk sering kali menandakan bahwa logika tersebut layak menjadi function terpisah. Sebagai panduan:

  • bila local function lebih panjang dari 15-20 baris, pertimbangkan menjadikannya private function di class atau top-level function
  • bila local function dipanggil dari lebih dari satu function induk, pindahkan ke level yang lebih luas
  • bila local function tidak memanfaatkan closure, ia sebenarnya tidak perlu menjadi local

Referensi Lanjutan #

  • Kotlin functions — panduan resmi local function yang dideklarasikan di dalam function lain

Ringkasan #

Local function memungkinkan kita mendeklarasikan function penolong di dalam function induk. Closure memberi akses ke variabel luar tanpa perlu meneruskan parameter berulang. Local function menjaga namespace tetap bersih dengan membatasi visibility ke function induk. Pada chapter Extension Functions berikutnya, kita akan melihat bagaimana Kotlin memungkinkan kita menambahkan method ke class yang sudah ada tanpa memodifikasi kode sumber class tersebut.