extension property — mechanismus Kotlinu, který umožňuje přidávat nové vlastnosti ke stávajícím třídám bez dědičnosti a bez změny zdrojového kódu. Na rozdíl od extension functions, vlastnosti-rozšíření nemohou ukládat stav — jsou deklarovány pouze s getterem a volitelně setterem, protože nemají backing field. Podle Kotlin Documentation, 2025 jsou extension properties kompilovány do statických metod getter a setter s receiver jako prvním parametrem.
Hlavní body
extension property — je syntaktická konstrukce Kotlinu, která přidává vlastnost k existujícímu typu bez změny jeho deklarace. Vlastnost je deklarována s uvedením receiver-typu a povinně obsahuje getter. Klíčový rozdíl oproti běžným vlastnostem — chybějící backing field: extension property nemůže ukládat data, pouze je počítá na základě receiver-objektu.
Podle Kotlin Foundation Survey (2024) jsou extension properties méně populární než extension functions — asi 45% vývojářů je používá pravidelně. To je způsobeno omezením chybějícího stavu, což zužuje oblast použití. Nicméně pro počítané vlastnosti logicky spojené s typem jsou extension properties nejvýstižnější možností.
Extension properties jsou kompilovány do dvojice statických metod getter a setter. Na úrovni bajtkódu není rozdíl mezi voláním extension property a extension function — obě se stávají statickými metodami s parametrem receiver. Podle údajů JetBrains (Kotlin Docs, 2025) je režie zcela nulová.
Používejte extension properties pro krátké počítané hodnoty, které by měly vypadat jako vlastnosti, ne jako volání metod — to zlepšuje čitelnost kódu a dodržuje princip jednotného přístupu.
Pro deklaraci extension property se používá syntaxe podobná běžné vlastnosti, ale s prefixem receiver-typu. val deklaruje read-only extension property s povinným getterem, var — mutable s getterem a volitelným setterem.
// Extension property pouze pro čtení
val String.isEmail: Boolean
get() = this.contains("@") && this.contains(".")
// Volání
val valid = "test@test.com".isEmail
Všimněte si: extension property se volá bez závorek — str.isEmail, nikoli str.isEmail(). To je klíčový rozdíl mezi extension property a extension function: property vypadá jako pole, i když je ve skutečnosti počítána prostřednictvím getteru.
Extension properties mohou být zobecněné — receiver může používat generické parametry. To umožňuje vytvářet univerzální vlastnosti pracující s jakýmkoli typem kolekce.
val List<T>.secondOrNull: T?
get() = if (size >= 2) this[1] else null
val items = listOf("a", "b", "c")
val second = items.secondOrNull // "b"
Vlastnost secondOrNull funguje pro libovolný typ T a vrací druhý prvek seznamu nebo null, pokud je prvků méně než dva. To je typický příklad, kde je extension property vhodnější než funkce — přístup vypadá jako čtení pole.
Extension property nemůže mít backing field, protože není přidávána do metadat třídy — existuje pouze jako dvojice statických funkcí getter/setter. Backing field (klíčové slovo field v Kotlinu) — je interní pole třídy, které ukládá hodnotu vlastnosti. Extension property nemá přístup k interní struktuře třídy.
// ❌ CHYBA: extension property nemůže mít backing field
var String.cachedValue: String
get() = "computed"
set(value) {
field = value // pole není přístupné!
}
// ✅ SPRÁVNĚ: použijte externí úložiště
val cache = MutableMap<String, String>()
var String.cachedValue: String
get() = cache[this] ?: ""
set(value) { cache[this] = value }
Externí Map v příkladu řeší problém ukládání, ale vytváří jiný — únik paměti. Hodnoty získané prostřednictvím extension property žijí v Map věčně, pokud nejsou vyčištěny. Toto omezení činí extension properties nevhodnými pro ukládání do mezipaměti nebo dočasných dat.
Pro ukládání do mezipaměti se doporučuje používání WeakHashMap nebo mechanismů s automatickým čištěním. JetBrains doporučuje vyhýbat se používání var extension properties s externím úložištěm v produkčním kódu bez pečlivé správy životního cyklu.
Volba mezi extension property a extension function závisí na sémantice: vlastnost popisuje charakteristiku objektu, funkce popisuje akci. Princip jednotného přístupu (Uniform Access Principle) říká: klient by neměl vědět, zda je hodnota počítána nebo ukládána. Pokud lze hodnotu prezentovat jako charakteristiku (délka, velikost, stav) — použijte property.
| Kritérium | Extension property | Extension function |
|---|---|---|
| Volání | Bez závorek: obj.property | Se závorkami: obj.function() |
| Sémantika | Charakteristika, atribut | Akce, operace |
| Backing field | Není podporován | Není relevantní |
| Parametry | Pouze getter/setter | Libovolné parametry |
| Výkon | Stejný (statická metoda) | Stejný (statická metoda) |
| Příklad | text.length | text.isEmail() |
Pravidlo je jednoduché: pokud operace přijímá parametry — použijte extension function. Pokud se jedná o jednoduchou počítanou hodnotu bez parametrů — extension property. Podle údajů Android Architecture Guide (Google, 2025) by měly být upřednostňovány extension properties pro přístup k datům a extension functions pro operace s vedlejšími účinky.
Extension property s klíčovým slovem var podporuje setter, ale bez možnosti ukládat hodnotu — setter obvykle provádí vedlejší účinek nebo ukládá data do externího úložiště. Syntaxe je analogická mutabilním vlastnostem tříd.
// Mutable extension property se setterem
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!
Vlastnost lastChar — klasický příklad z dokumentace Kotlinu. Getter vrací poslední znak StringBuilderu, setter jej nahrazuje novou hodnotou. Všimněte si: stav je ukládán v samotném StringBuilderu (prostřednictvím setCharAt), nikoli v samostatném poli — to je správné použití extension property.
V reálných projektech se extension properties nejčastěji používají pro zjednodušení přístupu k datům kolekcí, výpočet velikostí nebo stavů prvků UI a vytváření pohodlného API nad stávajícími třídami. Standardní knihovna Kotlinu aktivně používá tento mechanismus: size, indices, lastIndex pro kolekce — to jsou extension properties.
// Extension properties pro kolekce
val List<Int>.sumFast: Int
get() = fold(0) { acc, i -> acc + i }
val String.half: String
get() = this.substring(0, length / 2)
// Extension property pro Android View
val View.isVisible: Boolean
get() = visibility == View.VISIBLE
// Kontrola null prostřednictvím bezpečného receiveru
val String?.isNullOrBlank: Boolean
get() = this == null || this.isBlank()
Extension property isVisible pro View — příklad, který by měl znát každý Android vývojář. Místo view.visibility == View.VISIBLE lze psát view.isVisible. Není to jen kratší, ale čte se jako přirozený jazyk: „pokud je pohled viditelný“. I přes svou jednoduchost takové vlastnosti výrazně zlepšují čitelnost kódu.
Často kladené otázky
Ne, extension properties nelze deklarovat pro companion object ani object declaration. Mechanismus extension se aplikuje pouze na třídy, rozhraní a nullable typy. Pro object použijte běžné funkce nejvyšší úrovně.
Inline vlastnost (s modifikátorem inline) — mechanismus Kotlinu pro volání getteru/setteru bez vytváření objektu-vlastnosti. Extension property je vždy kompilována do statické metody, zatímco inline vlastnost je kompilována do volání bez obalu. Řeší různé úkoly: extension property přidává vlastnost k existujícímu typu, inline optimalizuje volání vlastních vlastností.
Ano, extension property může obsahovat anotace, ale pouze na úrovni deklarace. Getter nebo setter extension property nelze anotovat samostatně — na rozdíl od běžných vlastností třídy. Příklad: @JvmName(„getIsValid“) val String.isValid get() = true.
Ne, extension properties nelze deklarovat s companion object jako receiver. To je omezení jazyka — extension property funguje pouze s instancemi typů, zatímco companion object je statický kontext. Použijte extension funkce nejvyšší úrovně nebo konstanty.
Minimálně. Každá extension property přidává jednu statickou metodu getter (a volitelně setter) do zkompilovaného bajtkódu. Pro srovnání: vytvoření obalové třídy se stejnou vlastností přidává celou třídu. Extension properties — lehčí přístup k rozšíření funkcionality.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také