extension property — Kotlin mexanizmi olub, mövcud siniflərə miras almadan və mənbə kodunu dəyişdirmədən yeni xassələr əlavə etməyə imkan verir. Extension functions-dən fərqli olaraq, xassə-uzantılar vəziyyəti saxlaya bilməz — onlar yalnız getter və isteğə bağlı setter ilə elan edilir, çünki backing field-ları yoxdur. Kotlin Documentation, 2025-yə görə, extension properties getter və setter-in statik metodlarına receiver ilə birinci parametr kimi tərtib edilir.
Əsas məqamlar
extension property — elə Kotlin sintaktik konstruksiyasıdır ki, mövcud tipə onun elanını dəyişmədən xassə əlavə edir. Xassə receiver-tipinin göstərilməsi ilə elan edilir və məcburi olaraq getter ehtiva edir. Əsas fərq adi xassələrdən — backing field-ın olmaması: extension property məlumat saxlaya bilməz, yalnız onları receiver-obyekti əsasında hesablayır.
Kotlin Foundation Survey (2024)-yə görə, extension properties extension functions-dən daha az populyardır — onları təxminən 45% proqramçı müztərən istifadə edir. Bu, vəziyyətin olmaması məhdudiyyəti ilə bağlıdır ki, bu da tətbiq sahəsini daraldır. Bununla belə, tiplə məntiqi əlaqəli hesablanmış xassələr üçün extension properties ən yığcam seçimdir.
Extension properties bir cüt statik getter və setter metodlarına tərtib edilir. Bayt-kod səviyyəsində extension property və extension function çağırışı arasında fərq yoxdur — hər ikisi receiver parametri olan statik metodlara çevrilir. Məlumata görə JetBrains (Kotlin Docs, 2025), əlavə yük tamamilə yoxdur.
Extension properties-dən qısa hesablanmış dəyərlər üçün istifadə edin ki, onlar metod çağırışı kimi deyil, xassə kimi görünməlidir — bu kodun oxunaqlılığını yaxşılaşdırır və vahid giriş prinsipinə əməl edir.
Extension property elan etmək üçün adi xassəyə bənzər sintaksis istifadə olunur, lakin receiver-tipi prefiksi ilə. val məcburi getter ilə read-only extension property elan edir, var — getter və isteğə bağlı setter ilə mutable.
// Yalnız oxumaq üçün extension property
val String.isEmail: Boolean
get() = this.contains("@") && this.contains(".")
// Çağırış
val valid = "test@test.com".isEmail
Diqqət edin: extension property mötərizəsiz çağırılır — str.isEmail, str.isEmail() yox. Bu, extension property ilə extension function arasındakı əsas fərqdir: property sahə kimi görünür, baxmayaraq ki, əslində getter vasitəsilə hesablanır.
Extension properties ümumiləşdirilə bilər — receiver generic parametrlərdən istifadə edə bilər. Bu, istənilən kolleksiya tipi ilə işləyən universal xassələr yaratmağa imkan verir.
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 xassəsi istənilən T tipi üçün işləyir, siyahının ikinci elementini və ya elementlər ikidən az olduqda null qaytarır. Bu, extension property-nin funksiyadan daha uyğun olduğu tipik bir nümunədir — müraciət sahə oxunuşu kimi görünür.
Extension property backing field-ına malik ola bilməz, çünki sinif metadata-sına əlavə edilmir — yalnız bir cüt statik getter/setter funksiyası kimi mövcuddur. Backing field (Kotlin-də field açar sözü) — xassənin dəyərini saxlayan sinfin daxili sahəsidir. Extension property-nin sinfin daxili strukturuna çıxışı yoxdur.
// ❌ XƊTA: extension property-nin backing field-ı ola bilməz
var String.cachedValue: String
get() = "computed"
set(value) {
field = value // sahə əlçatan deyil!
}
// ✅ DÜZGÜN: xarici yaddaşdan istifadə edin
val cache = MutableMap<String, String>()
var String.cachedValue: String
get() = cache[this] ?: ""
set(value) { cache[this] = value }
Nümunədəki Xarici Map saxlama problemini həll edir, lakin başqa birini yaradır — yaddaş sızıntısı. Extension property vasitƏəsilə əldə edilən dəyərlər təmizlənməsə, Map-də əbədi yaşayır. Bu məhdudiyyət extension properties-i keşləmə və ya müvəqqəti məlumat saxlama üçün yararsız edir.
Keşləmə üçün WeakHashMap və ya avtomatik təmizləmə mexanizmlərindən istifadə etmək tövsiyə olunur. JetBrains, həyat dövrü idarçiliyi olmadan istehsalat kodunda xarici yaddaş ilə var extension properties istifadəsindən çəkinməyi tövsiyə edir.
Extension property ilə extension function arasında seçim semantikadan asılıdır: xassə obyektin xarakteristikasını təsvir edir, funksiya isə hərəkəti. Vahid giriş prinsipi (Uniform Access Principle) deyir: müştəri dəyərin hesablandığını və ya saxlandığını bilməməlidir. Əgər dəyəri xarakteristika kimi təqdim etmək olarsa (uzunluq, ölçü, status) — property istifadə edin.
| Kriteriya | Extension property | Extension function |
|---|---|---|
| Çağırış | Mötərizəsiz: obj.property | Mötərizə ilə: obj.function() |
| Semantika | Xarakteristika, atribut | Hərəkət, əməliyyat |
| Backing field | Dəstəklənmir | Tətbiq edilmir |
| Parametrlər | Yalnız getter/setter | İstənilən parametrlər |
| Performans | Eyni (statik metod) | Eyni (statik metod) |
| Nümunə | text.length | text.isEmail() |
Qayda sadədir: əgər əməliyyat parametr qəbul edirsə — extension function istifadə edin. Əgər bu parametrsiz sadə hesablanmış dəyərdirsə — extension property. Məlumata görə Android Architecture Guide (Google, 2025), məlumatlara giriş üçün extension properties-ə, yan təsirləri olan əməliyyatlar üçün isə extension functions-a üstünlük vermək lazımdır.
var açar sözü ilə extension property setter-i dəstəkləyir, lakin dəyəri saxlamaq imkanı olmadan — setter adətən yan təsir yerinə yetirir və ya məlumatları xarici yaddaşda saxlayır. Sintaksis siniflərin mutable xassələrinə bənzəyir.
// Setter ilə 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 xassəsi — Kotlin sənədlərindən klassik nümunə. Getter StringBuilder-in son simvolunu qaytarır, setter onu yeni dəyərlə əvəz edir. Diqqət edin: vəziyyət ayrıca sahədə deyil, birbaşa StringBuilder-də (setCharAt vasitəsilə) saxlanılır — bu extension property-nin düzgün istifadəsidir.
Real layihələrdə extension properties ən çox kolleksiya məlumatlarına girişi sadələşdirmək, UI elementlərinin ölçülərini və ya statuslarını hesablamaq və mövcud siniflər üzərində rahat API yaratmaq üçün istifadə olunur. Kotlin standart kitabxanası bu mexanizmdən fəal istifadə edir: size, indices, lastIndex — bunlar extension properties-dir.
// Kolleksiyalar üçün 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 üçün extension property
val View.isVisible: Boolean
get() = visibility == View.VISIBLE
// Təhlükəsiz receiver vasitəsilə null yoxlaması
val String?.isNullOrBlank: Boolean
get() = this == null || this.isBlank()
View üçün isVisible extension property — hər Android tərtibatçısının bilməli olduğu nümunədir. view.visibility == View.VISIBLE əvəzinə view.isVisible yazmaq olar. Bu, nəinki daha qısadır, həm də təbii dil kimi oxunur: “əgər görünürsə”. Sadəliyinə baxmayaraq, belə xassələr kodun oxunaqlılığını əhəmiyyətli dərəcədə yaxşılaşdırır.
Tez-tez verilən suallar
Xeyr, extension properties companion object və ya object declaration üçün elan edilə bilməz. Extension mexanizmi yalnız siniflərə, interfeyslərə və nullable tiplərə tətbiq olunur. Object üçün adi yuxarı səviyyəli funksiyalardan istifadə edin.
Inline xassə (inline modifikatoru ilə) — Kotlin mexanizmi olub, getter/setter-i xassə-obyekti yaratmadan çağırmağa imkan verir. Extension property həmişə statik metoda tərtib edilir, inline xassə isə çağırışı sarıcısız həyata keçirir. Onlar müxtəlif vəzifələri həll edir: extension property mövcud tipə xassə əlavə edir, inline isə öz xassələrinin çağırışlarını optimallaşdırır.
Bəli, extension property annotasiyalar ehtiva edə bilər, lakin yalnız elan səviyyəsində. Sinfin adi xassələrindən fərqli olaraq, extension property-nin getter və setterini ayrıca annotasiya etmək olmaz. Nümunə: @JvmName(“getIsValid”) val String.isValid get() = true.
Xeyr, extension properties companion object ilə receiver kimi elan edilə bilməz. Bu dil məhdudiyyətidir — extension property yalnız tip nümunələri ilə işləyir, companion object isə statik kontekstdir. Yuxarı səviyyəli extension funksiyalarından və ya sabitlərdən istifadə edin.
Minimal. Hər extension property tərtib edilmiş bayt-koda bir statik getter metodu (və isteğə bağlı setter) əlavə edir. Müqayisə üçün: eyni xassəyə malik sarıcı sinif yaratmaq bütöv bir sinif əlavə edir. Extension properties — funksionallığı genişləndirmək üçün daha yüngül yanaşmadır.
Xülasə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun