extension property — mekanisme Kotlin yang memungkinkan menambahkan properti baru ke kelas yang sudah ada tanpa pewarisan dan tanpa mengubah kode sumber. Berbeda dengan extension functions, properti-ekstensi tidak dapat menyimpan status — mereka dideklarasikan hanya dengan getter dan opsional setter, karena tidak memiliki backing field. Menurut Kotlin Documentation, 2025, extension properties dikompilasi menjadi metode statis getter dan setter dengan receiver sebagai parameter pertama.
Poin utama
extension property — adalah konstruksi sintaksis Kotlin yang menambahkan properti ke tipe yang sudah ada tanpa mengubah deklarasinya. Properti dideklarasikan dengan menentukan tipe receiver dan wajib mengandung getter. Perbedaan utama dari properti biasa — tidak adanya backing field: extension property tidak dapat menyimpan data, hanya menghitungnya berdasarkan objek receiver.
Menurut Kotlin Foundation Survey (2024), extension properties kurang populer dibandingkan extension functions — sekitar 45% pengembang menggunakannya secara teratur. Hal ini disebabkan oleh batasan tidak adanya status, yang mempersempit area penerapan. Meskipun demikian, untuk properti yang dihitung dan secara logis terkait dengan tipe, extension properties adalah opsi yang paling ringkas.
Extension properties dikompilasi menjadi sepasang metode statis getter dan setter. Pada level bytecode, tidak ada perbedaan antara pemanggilan extension property dan extension function — keduanya menjadi metode statis dengan parameter receiver. Menurut data JetBrains (Kotlin Docs, 2025), overhead sama sekali tidak ada.
Gunakan extension properties untuk nilai hitung pendek yang harus terlihat seperti properti, bukan seperti pemanggilan metode — ini meningkatkan keterbacaan kode dan mematuhi prinsip akses seragam.
Untuk mendeklarasikan extension property digunakan sintaksis yang mirip dengan properti biasa, tetapi dengan prefiks tipe receiver. val mendeklarasikan read-only extension property dengan getter wajib, var — mutable dengan getter dan setter opsional.
// Extension property hanya baca
val String.isEmail: Boolean
get() = this.contains("@") && this.contains(".")
// Panggilan
val valid = "test@test.com".isEmail
Perhatikan: extension property dipanggil tanpa tanda kurung — str.isEmail, bukan str.isEmail(). Ini adalah perbedaan utama antara extension property dan extension function: property terlihat seperti field, meskipun sebenarnya dihitung melalui getter.
Extension properties dapat digeneralisasi — receiver dapat menggunakan parameter generic. Ini memungkinkan pembuatan properti universal yang bekerja dengan tipe koleksi apa pun.
val List<T>.secondOrNull: T?
get() = if (size >= 2) this[1] else null
val items = listOf("a", "b", "c")
val second = items.secondOrNull // "b"
Properti secondOrNull bekerja untuk tipe T apa pun, mengembalikan elemen kedua dari daftar atau null jika elemen kurang dari dua. Ini adalah contoh tipikal di mana extension property lebih tepat daripada fungsi — aksesnya terlihat seperti membaca field.
Extension property tidak dapat memiliki backing field karena tidak ditambahkan ke metadata kelas — hanya ada sebagai sepasang fungsi statis getter/setter. Backing field (kata kunci field di Kotlin) — adalah field internal kelas yang menyimpan nilai properti. Extension property tidak memiliki akses ke struktur internal kelas.
// ❌ ERROR: extension property tidak dapat memiliki backing field
var String.cachedValue: String
get() = "computed"
set(value) {
field = value // field tidak dapat diakses!
}
// ✅ BENAR: gunakan penyimpanan eksternal
val cache = MutableMap<String, String>()
var String.cachedValue: String
get() = cache[this] ?: ""
set(value) { cache[this] = value }
Map eksternal dalam contoh memecahkan masalah penyimpanan, tetapi menciptakan masalah lain — kebocoran memori. Nilai yang diperoleh melalui extension property hidup di Map selamanya jika tidak dibersihkan. Batasan ini membuat extension properties tidak cocok untuk caching atau penyimpanan data sementara.
Untuk caching, disarankan menggunakan WeakHashMap atau mekanisme dengan pembersihan otomatis. JetBrains merekomendasikan untuk menghindari penggunaan var extension properties dengan penyimpanan eksternal dalam kode produksi tanpa manajemen siklus hidup yang cermat.
Pilihan antara extension property dan extension function tergantung pada semantik: properti menggambarkan karakteristik objek, fungsi menggambarkan tindakan. Prinsip akses seragam (Uniform Access Principle) mengatakan: klien tidak boleh tahu apakah nilai dihitung atau disimpan. Jika nilai dapat direpresentasikan sebagai karakteristik (panjang, ukuran, status) — gunakan property.
| Kriteria | Extension property | Extension function |
|---|---|---|
| Pemanggilan | Tanpa kurung: obj.property | Dengan kurung: obj.function() |
| Semantik | Karakteristik, atribut | Tindakan, operasi |
| Backing field | Tidak didukung | Tidak berlaku |
| Parameter | Hanya getter/setter | Parameter apa pun |
| Kinerja | Sama (metode statis) | Sama (metode statis) |
| Contoh | text.length | text.isEmail() |
Aturannya sederhana: jika operasi menerima parameter — gunakan extension function. Jika ini adalah nilai hitung sederhana tanpa parameter — extension property. Menurut Android Architecture Guide (Google, 2025), preferensi harus diberikan pada extension properties untuk akses data dan extension functions untuk operasi dengan efek samping.
Extension property dengan kata kunci var mendukung setter, tetapi tanpa kemampuan menyimpan nilai — setter biasanya melakukan tindakan sampingan atau menyimpan data di penyimpanan eksternal. Sintaksis analog dengan properti mutable kelas.
// Mutable extension property dengan setter
var StringBuilder.lastChar: Char
get() = this[length - 1]
set(value) {
this.setCharAt(length - 1, value)
}
val sb = StringBuilder("Kotlin")
println(sb.lastChar) // n
sb.lastChar = '!'
println(sb) // Kotli!
Properti lastChar — contoh klasik dari dokumentasi Kotlin. Getter mengembalikan karakter terakhir StringBuilder, setter menggantinya dengan nilai baru. Perhatikan: status disimpan di StringBuilder itu sendiri (melalui setCharAt), bukan di field terpisah — ini adalah penggunaan extension property yang benar.
Dalam proyek nyata, extension properties paling sering digunakan untuk menyederhanakan akses ke data koleksi, menghitung ukuran atau status elemen UI, dan membuat API yang nyaman di atas kelas yang sudah ada. Pustaka standar Kotlin secara aktif menggunakan mekanisme ini: size, indices, lastIndex untuk koleksi — ini adalah extension properties.
// Extension properties untuk koleksi
val List<Int>.sumFast: Int
get() = fold(0) { acc, i -> acc + i }
val String.half: String
get() = this.substring(0, length / 2)
// Extension property untuk Android View
val View.isVisible: Boolean
get() = visibility == View.VISIBLE
// Pemeriksaan null melalui receiver aman
val String?.isNullOrBlank: Boolean
get() = this == null || this.isBlank()
Extension property isVisible untuk View — contoh yang harus diketahui setiap pengembang Android. Alih-alih view.visibility == View.VISIBLE, Anda bisa menulis view.isVisible. Ini tidak hanya lebih pendek, tetapi terbaca seperti bahasa alami: “jika tampilan terlihat”. Meskipun sederhana, properti semacam itu secara signifikan meningkatkan keterbacaan kode.
Pertanyaan yang sering diajukan
Tidak, extension properties tidak dapat dideklarasikan untuk companion object atau object declaration. Mekanisme extension hanya berlaku untuk kelas, antarmuka, dan tipe nullable. Untuk object, gunakan fungsi biasa tingkat atas.
Properti inline (dengan pengubah inline) — mekanisme Kotlin untuk memanggil getter/setter tanpa membuat objek properti. Extension property selalu dikompilasi menjadi metode statis, sedangkan properti inline dikompilasi menjadi pemanggilan tanpa pembungkus. Mereka menyelesaikan tugas yang berbeda: extension property menambahkan properti ke tipe yang ada, inline mengoptimalkan pemanggilan properti sendiri.
Ya, extension property dapat mengandung anotasi, tetapi hanya pada tingkat deklarasi. Getter atau setter extension property tidak dapat dianotasi secara terpisah — tidak seperti properti kelas biasa. Contoh: @JvmName(“getIsValid”) val String.isValid get() = true.
Tidak, extension properties tidak dapat dideklarasikan dengan companion object sebagai receiver. Ini adalah batasan bahasa — extension property hanya bekerja dengan instance tipe, sedangkan companion object adalah konteks statis. Gunakan extension functions tingkat atas atau konstanta.
Minimal. Setiap extension property menambahkan satu metode statis getter (dan opsional setter) ke bytecode yang dikompilasi. Sebagai perbandingan: membuat kelas pembungkus dengan properti yang sama menambahkan seluruh kelas. Extension properties — pendekatan yang lebih ringan untuk memperluas fungsionalitas.
Kesimpulan
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.
Baca juga