Fungsi ekstensi di Kotlin: apa itu, sintaksis dan penerapan

Penulis: IT Sectr Diterbitkan: 2026-06-21 Waktu membaca: 9 mnt

fungsi ekstensi — mekanisme Kotlin yang memungkinkan penambahan metode baru ke kelas yang ada tanpa pewarisan dan tanpa mengubah kode sumber. Fungsi dideklarasikan dengan prefiks berupa tipe penerima dan dipanggil sebagai metode biasa dari tipe ini. Menurut Kotlin Documentation, 2025, fungsi ekstensi dikompilasi menjadi metode statis dengan parameter penerima pertama, yang menjamin nol overhead saat runtime dibandingkan dengan panggilan biasa.

Poin Utama

  • Fungsi ekstensi — metode dengan tipe penerima, dipanggil sebagai anggota kelas tanpa pewarisan
  • Tipe penerima ditunjukkan melalui titik sebelum nama fungsi: fun Type.method()
  • Dispatch statis — fungsi ekstensi tidak virtual, dipanggil berdasarkan tipe variabel
  • Import wajib: fungsi ekstensi bukan anggota kelas dan memerlukan import
  • Anggota kelas memiliki prioritas: jika metode cocok — anggota kelas dipanggil, bukan ekstensi

Apa itu fungsi ekstensi di Kotlin?

Fungsi ekstensi adalah fungsi yang dideklarasikan di luar kelas, tetapi dipanggil sebagai metodenya. Ia menerima tipe penerima yang ditambahkan metode baru. Di dalam fungsi, kata kunci this merujuk pada instance tipe penerima. Pendekatan ini memungkinkan perluasan kelas final, kelas pustaka pihak ketiga, dan bahkan tipe primitif tanpa membuat pembungkus.

Tidak seperti Java, di mana untuk menambahkan metode ke kelas yang ada memerlukan pewarisan atau kelas utilitas statis, Kotlin menawarkan solusi elegan tanpa boilerplate. Menurut data penelitian Kotlin Foundation (2024), fungsi ekstensi termasuk dalam lima fitur bahasa yang paling sering digunakan — 78% pengembang Kotlin menggunakannya dalam pekerjaan sehari-hari.

Kompilator Kotlin menerjemahkan fungsi ekstensi menjadi metode statis, di mana instance penerima diberikan sebagai argumen pertama. Ini berarti fungsi ekstensi tidak mengubah bytecode kelas target dan tidak melanggar enkapsulasi — hanya bidang dan metode publik penerima yang dapat diakses.

Gunakan fungsi ekstensi untuk menulis fungsi utilitas bersih yang secara logis terikat pada tipe tertentu, tetapi tidak dapat ditambahkan ke kode sumbernya.

Sintaksis fungsi ekstensi: deklarasi dan pemanggilan

Sintaksis dasar fungsi ekstensi: nama tipe penerima, titik, nama fungsi, kemudian parameter dan tipe kembalian. Di dalam fungsi, penerima dapat diakses melalui this.

kotlin
// Fungsi ekstensi untuk String
fun String.isEmail(): Boolean {
    return this.contains("@") && this.contains(".")
}

// Dipanggil sebagai metode String biasa
val result = "user@example.com".isEmail() // true

Dalam contoh ini, isEmail() menjadi tersedia untuk semua string. Di dalam fungsi, this adalah string itu sendiri tempat metode dipanggil. Kotlin memungkinkan menghilangkan this dalam sebagian besar kasus — cukup menulis contains("@") daripada this.contains("@").

Fungsi ekstensi dengan parameter

Fungsi ekstensi dapat menerima parameter tambahan dan mengembalikan nilai dari tipe apa pun. Ini menjadikannya fungsi yang lengkap, bukan hanya gula sintaksis.

kotlin
fun List<Int>.defaultIfEmpty(default: Int): List<Int> {
    if (this.isEmpty()) return listOf(default)
    return this
}

val populated = listOf(1, 2).defaultIfEmpty(0)
val empty = listOf<Int>().defaultIfEmpty(0)

Parameter default menentukan nilai yang dikembalikan untuk daftar kosong. Fungsi ekstensi bisa generic — tipe List digeneralisasi, meskipun dalam contoh digunakan List konkret.

Dispatch statis dan penerima

Fungsi ekstensi di Kotlin menggunakan dispatch statis, bukan virtual. Ini adalah perbedaan utama dari metode kelas biasa. Fungsi ekstensi mana yang akan dipanggil ditentukan pada fase kompilasi berdasarkan tipe statis variabel, bukan tipe aktualnya saat runtime.

kotlin
open class Animal
class Dog : Animal()

fun Animal.speak() = "Suara hewan"
fun Dog.speak() = "Gukguk"

fun test() {
    val animal: Animal = Dog()
    println(animal.speak()) // "Suara hewan" — tipe statis Animal

    val dog: Dog = Dog()
    println(dog.speak()) // "Gukguk" — tipe statis Dog
}

Meskipun variabel animal menunjuk ke instance Dog, fungsi ekstensi untuk Animal dipanggil, karena tipe statis variabel adalah Animal. Jika speak() adalah metode virtual kelas, Dog.speak() akan dipanggil. Properti ini penting untuk dipertimbangkan saat merancang API berbasis fungsi ekstensi.

Import dan ruang lingkup visibilitas fungsi ekstensi

Fungsi ekstensi bukan anggota kelas — ini adalah fungsi biasa yang memerlukan import untuk digunakan di file lain. Kotlin menawarkan dua varian import: berdasarkan nama fungsi atau dengan penggantian nama.

kotlin
// Import berdasarkan nama
import com.example.extensions.isEmail

// Import dengan alias (untuk menyelesaikan konflik)
import com.example.extensions.isEmail as isValidEmail

// Panggilan setelah import
val valid = "test@test.com".isEmail()

Penggantian nama melalui as berguna saat konflik nama — misalnya, jika dua pustaka menyediakan fungsi ekstensi dengan nama yang sama untuk tipe yang sama. Dalam hal ini, salah satunya dapat diimpor dengan nama lain dan dipanggil melalui nama baru.

Ruang lingkup visibilitas

Fungsi ekstensi dapat dideklarasikan pada berbagai tingkat:

TingkatVisibilitasContoh
Top-levelSeluruh proyek setelah importfun String.isEmail()
Member extensionDi dalam kelas pemilikclass A { fun B.ext() }
LocalDi dalam fungsifun test() { fun String.ext() }

Member extension functions — kasus khusus ketika fungsi ekstensi dideklarasikan di dalam kelas lain. Dalam hal ini, di dalam fungsi ekstensi, baik penerima (this fungsi) maupun anggota kelas eksternal dapat diakses.

Prioritas anggota kelas atas ekstensi

Jika kelas memiliki metode dengan tanda tangan yang sama dengan fungsi ekstensi, anggota kelas selalu dipanggil. Fungsi ekstensi tidak pernah menimpa metode kelas — ini adalah keputusan arsitektural untuk mencegah penimpaan yang tidak disengaja.

kotlin
class User {
    fun greet() = "Halo dari kelas"
}

fun User.greet() = "Hello from extension"

fun main() {
    val user = User()
    println(user.greet()) // "Halo dari kelas"
}

Bahkan jika fungsi ekstensi didefinisikan kemudian dan memiliki tanda tangan yang sama, kompilator akan memilih metode kelas. Kompilator Kotlin mengeluarkan peringatan saat mendeteksi situasi seperti itu. Satu-satunya cara untuk memanggil fungsi ekstensi dengan adanya metode kelas adalah dengan memanggilnya sebagai fungsi biasa: greet(user).

Contoh praktis fungsi ekstensi

Dalam pengembangan Android, fungsi ekstensi telah menjadi alat standar untuk bekerja dengan View, Context, dan fragmen. Pustaka Android KTX dibangun di atas fungsi ekstensi, menyediakan pembungkus yang nyaman untuk API Android.

kotlin
// Fungsi ekstensi untuk bekerja dengan View
fun View.show() {
    visibility = View.VISIBLE
}

fun View.hide() {
    visibility = View.GONE
}

// Fungsi ekstensi untuk Context — toast
fun Context.toast(message: String) {
    Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}

// Fungsi ekstensi sebagai pembangun DSL
fun String.colorFormat(color: String): String =
    "$color$this\u001b[0m"

Fungsi ekstensi toast() membuat panggilan yang bergantung pada Context menjadi ringkas: alih-alih menulis Toast.makeText(context, message, length).show() cukup menulis context.toast("Teks"). Ini mengurangi boilerplate dan membuat kode lebih mudah dibaca.

Pertanyaan yang Sering Diajukan

Bisakah fungsi ekstensi ditimpa di subkelas?

Tidak, fungsi ekstensi menggunakan dispatch statis. Jika Anda mendeklarasikan fungsi ekstensi untuk kelas dasar dan yang sama untuk subkelas, mana yang akan dipanggil ditentukan oleh tipe statis variabel pada fase kompilasi, bukan tipe aktual saat runtime.

Bagaimana fungsi ekstensi bekerja dengan tipe nullable?

Fungsi ekstensi dapat dideklarasikan untuk tipe penerima nullable: fun String?.isNullOrEmail(). Di dalam fungsi seperti itu, this bisa null, oleh karena itu perlu menggunakan operator panggilan aman atau pemeriksaan null eksplisit.

Apakah fungsi ekstensi memiliki overhead kinerja?

Tidak, fungsi ekstensi dikompilasi menjadi metode statis. Pada tingkat bytecode, panggilan fungsi ekstensi identik dengan panggilan metode statis dengan parameter penerima pertama. Tidak ada refleksi atau dispatch dinamis.

Bisakah properti ekstensi dideklarasikan untuk kelas?

Ya, properti ekstensi bekerja mirip dengan fungsi ekstensi, tetapi tidak dapat menyimpan status — hanya getter dan setter. Misalnya: val List<Int>.sum get() = reduce(Int::plus). Mereka juga dikompilasi menjadi metode statis getter/setter.

Apa perbedaan fungsi ekstensi dengan metode di kelas utilitas Java?

Di Java Anda menulis StringUtils.isEmail(str), di Kotlin — str.isEmail(). Perbedaannya tidak hanya pada sintaksis: fungsi ekstensi mendukung pelengkapan otomatis di IDE, meningkatkan keterbacaan rantai panggilan, dan memungkinkan IDE menyarankan fungsi yang relevan untuk tipe tertentu. Di Java, kemampuan semacam itu tidak ada.

Kesimpulan

  • Fungsi ekstensi — metode dengan tipe penerima, dipanggil sebagai anggota kelas tanpa pewarisan
  • Dispatch statis — pemilihan fungsi berdasarkan tipe statis, bukan tipe runtime
  • Nol overhead — dikompilasi menjadi metode statis dengan penerima sebagai parameter pertama
  • Import wajib untuk digunakan di file lain, alias dimungkinkan melalui as
  • Anggota kelas memiliki prioritas atas fungsi ekstensi dengan tanda tangan yang sama
  • Member extensions — ekstensi yang dideklarasikan di dalam kelas, memiliki akses ke anggotanya
  • Penerapan praktis — utilitas untuk String, View, Context, koleksi, dan pembangunan DSL

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga