extension property — bu Kotlin mexanizmi bo'lib, mavjud sinflarga meros olishsiz va manba kodini o'zgartirmasdan yangi xususiyatlar qo'shish imkonini beradi. Extension functions dan farqli o'laroq, xususiyat-kengaytmalar holatni saqlay olmaydi — ular faqat getter va ixtiyoriy ravishda setter bilan e'lon qilinadi, chunki ularning backing field i yo'q. Kotlin Documentation, 2025 ma'lumotlariga ko'ra, extension properties getter va setter ning statik metodlariga receiver birinchi parametr sifatida kompilyatsiya qilinadi.
Asosiy fikrlar
extension property — bu Kotlin ning sintaktik konstruktsiyasi bo'lib, mavjud turga uni e'lon qilishni o'zgartirmasdan xususiyat qo'shadi. Xususiyat receiver-turini ko'rsatish bilan e'lon qilinadi va majburiy ravishda getterni o'z ichiga oladi. Asosiy farq oddiy xususiyatlardan — backing field ning yo'qligi: extension property ma'lumotlarni saqlay olmaydi, balki ularni receiver-ob'ekti asosida hisoblaydi.
Kotlin Foundation Survey (2024) ma'lumotlariga ko'ra, extension properties extension functions dan kamroq mashhur — ularni taxminan 45% dasturchilar muntazam ishlatadi. Bu holatning yo'qligi cheklovi bilan bog'liq bo'lib, qo'llanish sohasini toraytiradi. Shunga qaramay, tur bilan mantiqiy bog'liq hisoblangan xususiyatlar uchun extension properties eng ixcham variantdir.
Extension properties bir juft statik getter va setter metodlariga kompilyatsiya qilinadi. Bayt-kod darajasida extension property va extension function chaqiruvi o'rtasida farq yo'q — ikkalasi ham receiver parametri bilan statik metodlarga aylanadi. Ma'lumotlarga ko'ra JetBrains (Kotlin Docs, 2025), qo'shimcha yuk butunlay yo'q.
Extension properties dan qisqa hisoblangan qiymatlar uchun foydalaning, ular metod chaqiruvi emas, balki xususiyat kabi ko'rinishi kerak — bu kod o'qiluvchanligini yaxshilaydi va yagona kirish prinsipiga amal qiladi.
Extension property e'lon qilish uchun oddiy xususiyatga o'xshash sintaksis ishlatiladi, lekin receiver-turi prefiksi bilan. val majburiy getter bilan read-only extension property e'lon qiladi, var — getter va ixtiyoriy setter bilan mutable.
// Faqat o'qish uchun extension property
val String.isEmail: Boolean
get() = this.contains("@") && this.contains(".")
// Chaqiruv
val valid = "test@test.com".isEmail
E'tibor bering: extension property qavssiz chaqiriladi — str.isEmail, str.isEmail() emas. Bu extension property va extension function o'rtasidagi asosiy farq: property maydon kabi ko'rinadi, garchi aslida getter orqali hisoblansa ham.
Extension properties umumlashtirilgan bo'lishi mumkin — receiver generic parametrlardan foydalanishi mumkin. Bu har qanday kolleksiya turi bilan ishlaydigan universal xususiyatlar yaratish imkonini beradi.
val List<T>.secondOrNull: T?
get() = if (size >= 2) this[1] else null
val items = listOf("a", "b", "c")
val second = items.secondOrNull // "b"
secondOrNull xususiyati har qanday T turi uchun ishlaydi, ro'yxatning ikkinchi elementini yoki elementlar ikkitadan kam bo'lsa null qaytaradi. Bu extension property funksiyadan ko'ra ko'proq mos keladigan odatiy misoldir — murojaat maydon o'qish kabi ko'rinadi.
Extension property backing field ga ega bo'lolmaydi, chunki u sinf metama'lumotlariga qo'shilmaydi — faqat statik getter/setter funksiyalari jufti sifatida mavjud. Backing field (Kotlin da field kalit so'zi) — bu xususiyat qiymatini saqlaydigan sinfning ichki maydoni. Extension property sinfning ichki tuzilishiga kirish imkoniga ega emas.
// ❌ XATO: extension property backing field ga ega bo'la olmaydi
var String.cachedValue: String
get() = "computed"
set(value) {
field = value // maydon mavjud emas!
}
// ✅ TO'G'RI: tashqi saqlashdan foydalaning
val cache = MutableMap<String, String>()
var String.cachedValue: String
get() = cache[this] ?: ""
set(value) { cache[this] = value }
Misoldagi Tashqi Map saqlash muammosini hal qiladi, ammo boshqasini keltirib chiqaradi — xotira oqishi. Extension property orqali olingan qiymatlar tozalanmasa, Map da abadiy yashaydi. Bu cheklov extension properties ni keshlash yoki vaqtinchalik ma'lumotlarni saqlash uchun yaroqsiz qiladi.
Keshlash uchun WeakHashMap yoki avtomatik tozalash mexanizmlaridan foydalanish tavsiya etiladi. JetBrains ishlab chiqarish kodida hayot siklini boshqarmasdan tashqi saqlash bilan var extension properties dan foydalanishdan qochishni tavsiya qiladi.
Extension property va extension function o'rtasidagi tanlov semantikaga bog'liq: xususiyat ob'ektning xarakteristikasini tavsiflaydi, funksiya esa — harakatni. Yagona kirish prinsipi (Uniform Access Principle) deydi: mijoz qiymat hisoblanayotganini yoki saqlanayotganini bilmasligi kerak. Agar qiymatni xarakteristika sifatida ko'rsatish mumkin bo'lsa (uzunlik, o'lcham, holat) — property dan foydalaning.
| Mezon | Extension property | Extension function |
|---|---|---|
| Chaqiruv | Qavssiz: obj.property | Qavs bilan: obj.function() |
| Semantika | Xarakteristika, atribut | Harakat, operatsiya |
| Backing field | Qo'llab-quvvatlanmaydi | Qo'llanilmaydi |
| Parametrlar | Faqat getter/setter | Har qanday parametrlar |
| Unumdorlik | Bir xil (statik metod) | Bir xil (statik metod) |
| Misol | text.length | text.isEmail() |
Qoida oddiy: agar operatsiya parametr qabul qilsa — extension function dan foydalaning. Agar bu parametrsiz oddiy hisoblangan qiymat bo'lsa — extension property. Ma'lumotlarga ko'ra Android Architecture Guide (Google, 2025), ma'lumotlarga kirish uchun extension properties ga, yon ta'sirli operatsiyalar uchun esa extension functions ga ustunlik berish kerak.
Var kalit so'zi bilan extension property setterni qo'llab-quvvatlaydi, lekin qiymatni saqlash imkoniyatisiz — setter odatda yon ta'sirni bajaradi yoki ma'lumotlarni tashqi saqlashda saqlaydi. Sintaksis sinflarning mutable xususiyatlariga o'xshaydi.
// Setter bilan Mutable extension property
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!
lastChar xususiyati — Kotlin hujjatlaridan klassik misol. Getter StringBuilder ning oxirgi belgisini qaytaradi, setter uni yangi qiymat bilan almashtiradi. E'tibor bering: holat alohida maydonda emas, balki StringBuilder ning o'zida (setCharAt orqali) saqlanadi — bu extension property dan to'g'ri foydalanishdir.
Haqiqiy loyihalarda extension properties ko'pincha kolleksiya ma'lumotlariga kirishni soddalashtirish, UI elementlarining o'lchamlari yoki holatlarini hisoblash va mavjud sinflar ustida qulay API yaratish uchun ishlatiladi. Kotlin standart kutubxonasi bu mexanizmdan faol foydalanadi: size, indices, lastIndex — bular extension properties dir.
// Kolleksiyalar uchun extension properties
val List<Int>.sumFast: Int
get() = fold(0) { acc, i -> acc + i }
val String.half: String
get() = this.substring(0, length / 2)
// Android View uchun extension property
val View.isVisible: Boolean
get() = visibility == View.VISIBLE
// Xavfsiz receiver orqali null tekshirish
val String?.isNullOrBlank: Boolean
get() = this == null || this.isBlank()
View uchun isVisible extension property — har bir Android dasturchisi bilishi kerak bo'lgan misol. view.visibility == View.VISIBLE o'rniga view.isVisible yozish mumkin. Bu nafaqat qisqaroq, balki tabiiy til kabi o'qiladi: “agar ko'rinadigan bo'lsa”. Oddiyligiga qaramay, bunday xususiyatlar kod o'qiluvchanligini sezilarli darajada yaxshilaydi.
Tez-tez beriladigan savollar
Yo'q, extension properties companion object yoki object declaration uchun e'lon qilinishi mumkin emas. Extension mexanizmi faqat sinflar, interfeyslar va nullable turlarga nisbatan qo'llaniladi. Object uchun oddiy yuqori darajadagi funksiyalardan foydalaning.
Inline xususiyat (inline modifikatori bilan) — Kotlin mexanizmi bo'lib, getter/setterni xususiyat-ob'ektini yaratmasdan chaqirish imkonini beradi. Extension property har doim statik metodga kompilyatsiya qilinadi, inline xususiyat esa — o'ramsiz chaqiruvga. Ular turli vazifalarni hal qiladi: extension property mavjud turga xususiyat qo'shadi, inline o'z xususiyatlarining chaqiruvlarini optimallashtiradi.
Ha, extension property annotatsiyalarni o'z ichiga olishi mumkin, lekin faqat e'lon darajasida. Sinflarning oddiy xususiyatlaridan farqli o'laroq, extension property ning getter yoki setterini alohida annotatsiya qilib bo'lmaydi. Misol: @JvmName(“getIsValid”) val String.isValid get() = true.
Yo'q, extension properties companion object bilan receiver sifatida e'lon qilinishi mumkin emas. Bu til cheklovi — extension property faqat tur namunalari bilan ishlaydi, companion object esa statik kontekstdir. Yuqori darajadagi extension funksiyalardan yoki konstantalardan foydalaning.
Minimal. Har bir extension property kompilyatsiya qilingan bayt-kodga bitta statik getter metodini (va ixtiyoriy setter) qo'shadi. Taqqoslash uchun: bir xil xususiyatga ega o'rovchi sinf yaratish butun bir sinfni qo'shadi. Extension properties — funksionallikni kengaytirishning engilroq yondashuvidir.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.