Kotlin menyediakan lima scope functions bawaan: let, run, with, apply, dan also. Kelima function ini membantu mengelompokkan operasi pada objek yang sama, menangani null-safety, dan menyisipkan side effect tanpa merusak chain. Pada chapter ini kita akan melihat ringkasan kelima scope functions, perbandingan tegas antara receiver (this vs it) dan nilai kembalian (objek vs lambda result), serta panduan memilih function yang tepat untuk setiap situasi. Chapter ini menjadi pengantar untuk chapter-chapter khusus yang membahas setiap function lebih mendalam.
Apa Itu Scope Functions #
Scope functions adalah function bawaan standard library yang tujuan utamanya adalah membentuk scope sementara di mana sebuah objek tersedia tanpa prefix. Kelima function ini tidak melakukan hal yang tidak bisa kita lakukan tanpa mereka — manfaat utamanya adalah keterbacaan dan kekompakan kode.
val tugas = Tugas(1, "Belajar Kotlin")
val a = tugas.let { it.judul.uppercase() } // returns lambda result
val b = tugas.run { "Tugas #$id: $judul" } // returns lambda result
val c = with(tugas) { "[ID $id] $judul" } // returns lambda result (not extension)
val d = tugas.apply { judul = "Belajar Lanjut" } // returns the object
val e = tugas.also { println("Log: ${it.judul}") } // returns the objectTabel Perbandingan Scope Functions #
| Function | Receiver | Return | Bentuk | Use Case Utama |
|---|---|---|---|---|
let | it | lambda result | extension | Null-safety, transformasi |
run | this | lambda result | extension | Eksekusi blok pada receiver |
with | this | lambda result | function biasa | Mengelompokkan panggilan |
apply | this | objek (receiver) | extension | Konfigurasi objek |
also | it | objek (receiver) | extension | Side effect (log, debug) |
Contoh Kelima Scope Functions #
Mari kita lihat semua scope functions dalam satu file yang dapat dijalankan, dengan chaining di akhir.
// scope_functions.kt
// Lima scope functions: let, run, with, apply, also.
data class Tugas(val id: Int, var judul: String, var selesai: Boolean = false)
fun main() {
val tugas = Tugas(1, "Belajar Kotlin")
// let — receiver `it`, mengembalikan lambda result.
val judulKapital = tugas.let { it.judul.uppercase() }
println("let result: $judulKapital")
// run — receiver `this`, mengembalikan lambda result.
val ringkasan = tugas.run {
"Tugas #$id: $judul (selesai=$selesai)"
}
println("run result: $ringkasan")
// with — bukan extension, receiver `this`, mengembalikan lambda result.
val cetakan = with(tugas) {
"[ID $id] $judul"
}
println("with result: $cetakan")
// apply — receiver `this`, mengembalikan objek.
val dikonfigurasi = tugas.apply {
judul = "Belajar Kotlin Lanjut"
selesai = false
}
println("apply result: $dikonfigurasi")
// also — receiver `it`, mengembalikan objek.
val dilihat = tugas.also {
println(" (mencatat tugas: ${it.judul})")
}
println("also result: $dilihat")
// Chaining: apply untuk konfigurasi, lalu also untuk logging.
val final = Tugas(2, "Draft")
.apply {
judul = "Belajar Scope Functions"
selesai = true
}
.also { println(" Tugas siap: ${it.judul}") }
.let { "${it.id}: ${it.judul}" }
println("Hasil chaining: $final")
}Output yang Dihasilkan:
let result: BELAJAR KOTLIN
run result: Tugas #1: Belajar Kotlin (selesai=false)
with result: [ID 1] Belajar Kotlin
apply result: Tugas(id=1, judul=Belajar Kotlin Lanjut, selesai=false)
(mencatat tugas: Belajar Kotlin Lanjut)
also result: Tugas(id=1, judul=Belajar Kotlin Lanjut, selesai=false)
Tugas siap: Belajar Scope Functions
Hasil chaining: 2: Belajar Scope FunctionsMari kita telaah baris-baris kode di atas:
- Baris 9 (
tugas.let { it.judul.uppercase() }):letmemberi akses ke objek viait(parameter implisit). Hasil block (Stringkapital) menjadi nilai kembalian. Cocok untuk transformasi nilai. - Baris 13 (
tugas.run { "Tugas #$id: $judul (selesai=$selesai)" }):runmemberi akses ke objek viathis. Karenathisimplisit, kita memanggilid,judul,selesaitanpa prefix. Hasil block (string ringkasan) menjadi nilai kembalian. - Baris 19 (
with(tugas) { "[ID $id] $judul" }):withbukan extension function — menerima objek sebagai parameter pertama. Di dalam block,thisadalah objek. Hasil block menjadi nilai kembalian. - Baris 25 (
tugas.apply { judul = "Belajar Kotlin Lanjut"; selesai = false }):applymemberi akses viathis. Di dalam block kita mengubah property objek. Mengembalikan objek itu sendiri (bukan hasil block). Cocok untuk konfigurasi. - Baris 31 (
tugas.also { println(" (mencatat tugas: ${it.judul})") }):alsomemberi akses viait. Block biasanya berisi side effect (log, debug). Mengembalikan objek itu sendiri — tidak terpengaruh oleh hasil block. - Baris 38-45 (
Tugas(2, "Draft").apply { ... }.also { ... }.let { ... }): chaining tiga scope functions.applymengonfigurasi objek baru,alsomencatat log,letmengubah menjadi string ringkasan. Hasil akhir adalah string.
Panduan Memilih Scope Function #
| Tujuan | Pilih | Alasan |
|---|---|---|
Null-safety (obj?.let { ... }) | let | Safe-call + transformasi |
| Transformasi nilai ke tipe lain | let atau run | Kembalian lambda result |
| Konfigurasi objek (builder) | apply | Kembalian objek |
| Side effect tanpa ganggu chain | also | Kembalian objek, it eksplisit |
| Mengelompokkan beberapa panggilan pada objek | with | Sintaks function biasa, this |
| Eksekusi block pada receiver, ambil hasil | run | Extension + lambda result |
this vs it — Pilihan Stylistic #
Receiver this (apply, run, with) membuat kode di dalam block terbaca seperti method class — tanpa prefix. Receiver it (let, also) lebih eksplisit dan bisa diganti nama bila konteks memerlukan:
// `this` — akses tanpa prefix
tugas.apply { judul = "Baru" }
// `it` — eksplisit, bisa rename
tugas.also { t -> println(t.judul) }Referensi Lanjutan #
- Scope functions
— panduan resmi
let,run,with,apply,also - Higher-order functions and lambdas — dasar lambda yang dipakai scope function
Penutup #
Kelima scope functions menyediakan alat ringkas untuk pola umum: konfigurasi objek, transformasi nilai, null-safety, dan side effect. Dengan mengingat tabel perbandingan receiver dan return value, kita dapat memilih function yang tepat untuk setiap situasi. Selanjutnya, kita akan mendalami setiap function satu per satu — mulai dari let yang paling sering dipakai untuk null-safety dan transformasi nilai.