extension property — isang mekanismo ng Kotlin na nagbibigay-daan sa pagdagdag ng mga bagong property sa mga umiiral na klase nang walang inheritance at walang pagbabago sa source code. Hindi tulad ng extension functions, ang mga property-extension ay hindi makapag-imbak ng estado — ang mga ito ay idineklara lamang na may getter at opsyonal na setter, dahil wala silang backing field. Ayon sa Kotlin Documentation, 2025, ang extension properties ay ina-compile sa mga static na pamamaraan ng getter at setter na may receiver bilang unang parameter.
Mga pangunahing punto
extension property — ay isang syntactic na konstruksyon ng Kotlin na nagdadagdag ng property sa isang umiiral na uri nang hindi binabago ang deklarasyon nito. Ang property ay idineklara na may pagtukoy sa receiver-type at obligadong naglalaman ng getter. Ang pangunahing pagkakaiba mula sa mga ordinaryong property — ang kawalan ng backing field: ang extension property ay hindi makapag-imbak ng data, kinakalkula lamang ang mga ito batay sa receiver-object.
Ayon sa Kotlin Foundation Survey (2024), ang extension properties ay hindi gaanong popular kaysa sa extension functions — humigit-kumulang 45% ng mga developer ang regular na gumagamit ng mga ito. Ito ay dahil sa limitasyon ng kawalan ng estado, na nagpapaliit sa lugar ng aplikasyon. Gayunpaman, para sa mga kalkuladong property na lohikal na nauugnay sa uri, ang extension properties ay ang pinakakompaktong opsyon.
Ang extension properties ay ina-compile sa isang pares ng mga static na pamamaraan ng getter at setter. Sa antas ng bytecode, walang pagkakaiba sa pagitan ng pagtawag ng extension property at extension function — pareho silang nagiging static na pamamaraan na may parameter na receiver. Ayon sa datos ng JetBrains (Kotlin Docs, 2025), ang overhead ay ganap na wala.
Gamitin ang extension properties para sa mga maikling kalkuladong halaga na dapat magmukhang mga property, hindi mga tawag sa pamamaraan — pinapabuti nito ang pagiging madaling mabasa ng code at sumusunod sa prinsipyo ng pantay na pag-access.
Para sa pagdedeklara ng extension property, ginagamit ang syntax na katulad ng ordinaryong property, ngunit may prefix ng receiver-type. val ay nagdedeklara ng read-only extension property na may obligadong getter, var — mutable na may getter at opsyonal na setter.
// Read-only extension property
val String.isEmail: Boolean
get() = this.contains("@") && this.contains(".")
// Tawag
val valid = "test@test.com".isEmail
Pansinin: ang extension property ay tinatawag nang walang panaklong — str.isEmail, hindi str.isEmail(). Ito ang pangunahing pagkakaiba sa pagitan ng extension property at extension function: ang property ay mukhang isang field, kahit na sa katunayan ito ay kinakalkula sa pamamagitan ng getter.
Ang extension properties ay maaaring gawing generic — ang receiver ay maaaring gumamit ng mga generic na parameter. Ito ay nagbibigay-daan sa paglikha ng mga unibersal na property na gumagana sa anumang uri ng koleksyon.
val List<T>.secondOrNull: T?
get() = if (size >= 2) this[1] else null
val items = listOf("a", "b", "c")
val second = items.secondOrNull // "b"
Ang property na secondOrNull ay gumagana para sa anumang uri T, na bumabalik ng pangalawang elemento ng listahan o null kung may mas kaunti sa dalawang elemento. Ito ay isang tipikal na halimbawa kung saan ang extension property ay mas angkop kaysa sa isang function — ang pag-access ay mukhang pagbabasa ng isang field.
Ang extension property ay hindi maaaring magkaroon ng backing field dahil hindi ito idinaragdag sa metadata ng klase — ito ay umiiral lamang bilang isang pares ng mga static na getter/setter function. Backing field (ang keyword na field sa Kotlin) — ay ang panloob na field ng klase na nag-iimbak ng halaga ng property. Ang extension property ay walang access sa panloob na istraktura ng klase.
// ❌ ERROR: ang extension property ay hindi maaaring magkaroon ng backing field
var String.cachedValue: String
get() = "computed"
set(value) {
field = value // ang field ay hindi ma-access!
}
// ✅ TAMA: gumamit ng panlabas na imbakan
val cache = MutableMap<String, String>()
var String.cachedValue: String
get() = cache[this] ?: ""
set(value) { cache[this] = value }
Ang panlabas na Map sa halimbawa ay lumulutas sa problema ng pag-iimbak, ngunit lumilikha ng isa pa — pagtagas ng memorya. Ang mga halaga na nakuha sa pamamagitan ng extension property ay nabubuhay sa Map magpakailanman kung hindi linisin. Ang limitasyong ito ay ginagawang hindi angkop ang extension properties para sa caching o pag-iimbak ng pansamantalang data.
Para sa caching, inirerekomenda ang paggamit ng WeakHashMap o mga mekanismo na may awtomatikong paglilinis. Inirerekomenda ng JetBrains na iwasan ang paggamit ng var extension properties na may panlabas na imbakan sa production code nang walang maingat na pamamahala ng lifecycle.
Ang pagpili sa pagitan ng extension property at extension function ay nakadepende sa semantika: ang property ay naglalarawan ng katangian ng isang bagay, ang function ay naglalarawan ng isang aksyon. Ang prinsipyo ng pantay na pag-access (Uniform Access Principle) ay nagsasabi: ang kliyente ay hindi dapat malaman kung ang halaga ay kinakalkula o iniimbak. Kung ang halaga ay maaaring ilarawan bilang isang katangian (haba, laki, status) — gamitin ang property.
| Kriterya | Extension property | Extension function |
|---|---|---|
| Tawag | Walang panaklong: obj.property | May panaklong: obj.function() |
| Semantika | Katangian, atributo | Aksyon, operasyon |
| Backing field | Hindi sinusuportahan | Hindi naaangkop |
| Parameter | Getter/setter lamang | Anumang parameter |
| Pagganap | Pareho (static na pamamaraan) | Pareho (static na pamamaraan) |
| Halimbawa | text.length | text.isEmail() |
Ang patakaran ay simple: kung ang operasyon ay tumatanggap ng mga parameter — gamitin ang extension function. Kung ito ay isang simpleng kalkuladong halaga na walang parameter — extension property. Ayon sa Android Architecture Guide (Google, 2025), ang kagustuhan ay dapat ibigay sa extension properties para sa pag-access ng data at extension functions para sa mga operasyon na may mga side effect.
Ang extension property na may keyword na var ay sumusuporta sa setter, ngunit walang kakayahang mag-imbak ng halaga — ang setter ay karaniwang nagsasagawa ng side effect o nagse-save ng data sa isang panlabas na imbakan. Syntax ay kahalintulad sa mutable property ng mga klase.
// Mutable extension property na may 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!
Ang property na lastChar — isang klasikong halimbawa mula sa dokumentasyon ng Kotlin. Ang getter ay bumabalik ng huling karakter ng StringBuilder, ang setter ay pinapalitan ito ng bagong halaga. Pansinin: ang estado ay iniimbak sa StringBuilder mismo (sa pamamagitan ng setCharAt), hindi sa isang hiwalay na field — ito ay tamang paggamit ng extension property.
Sa mga tunay na proyekto, ang extension properties ay kadalasang ginagamit para sa pagpapasimple ng pag-access sa data ng koleksyon, pagkalkula ng mga sukat o status ng mga elemento ng UI, at paglikha ng maginhawang API sa ibabaw ng mga umiiral na klase. Ang standard library ng Kotlin ay aktibong gumagamit ng mekanismong ito: size, indices, lastIndex para sa mga koleksyon — ito ay mga extension properties.
// Extension properties para sa mga koleksyon
val List<Int>.sumFast: Int
get() = fold(0) { acc, i -> acc + i }
val String.half: String
get() = this.substring(0, length / 2)
// Extension property para sa Android View
val View.isVisible: Boolean
get() = visibility == View.VISIBLE
// Null check sa pamamagitan ng ligtas na receiver
val String?.isNullOrBlank: Boolean
get() = this == null || this.isBlank()
Ang extension property na isVisible para sa View — isang halimbawa na dapat malaman ng bawat Android developer. Sa halip na view.visibility == View.VISIBLE ay maaaring magsulat ng view.isVisible. Ito ay hindi lamang mas maikli, ngunit binabasa tulad ng natural na wika: “kung ang view ay nakikita”. Sa kabila ng pagiging simple, ang mga naturang property ay makabuluhang nagpapabuti sa pagiging madaling mabasa ng code.
Mga madalas itanong
Hindi, ang extension properties ay hindi maaaring ideklara para sa companion object o object declaration. Ang mekanismo ng extension ay nalalapat lamang sa mga klase, interface at nullable na uri. Para sa object, gumamit ng mga ordinaryong function sa pinakamataas na antas.
Ang inline na property (na may modifier na inline) — mekanismo ng Kotlin para sa pagtawag ng getter/setter nang hindi lumilikha ng object-property. Extension property ay palaging ina-compile sa isang static na pamamaraan, habang ang inline na property ay ina-compile sa isang tawag na walang wrapper. Nilulutas nila ang magkakaibang gawain: ang extension property ay nagdaragdag ng property sa isang umiiral na uri, ang inline ay nag-o-optimize ng mga tawag ng sariling property.
Oo, ang extension property ay maaaring maglaman ng mga anotasyon, ngunit lamang sa antas ng deklarasyon. Hindi maaaring anotahan nang hiwalay ang getter o setter ng extension property — hindi tulad ng mga ordinaryong property ng klase. Halimbawa: @JvmName(“getIsValid”) val String.isValid get() = true.
Hindi, ang extension properties ay hindi maaaring ideklara na may companion object bilang receiver. Ito ay isang limitasyon ng wika — ang extension property ay gumagana lamang sa mga instance ng mga uri, at ang companion object ay isang static na konteksto. Gumamit ng extension functions sa pinakamataas na antas o mga constant.
Minimal. Bawat extension property ay nagdaragdag ng isang static na pamamaraan ng getter (at opsyonal na setter) sa naka-compile na bytecode. Para sa paghahambing: ang paglikha ng isang wrapper class na may parehong property ay nagdaragdag ng isang buong klase. Extension properties — mas magaan na diskarte sa pagpapalawak ng functionality.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din