Extension property у Kotlin — шта је, синтакса и примена

Аутор: IT Sectr Објављено: 2026-06-21 Време читања: 8 мин

extension property — механизам у Kotlin који омогућује додавање нових својстава постојећим класама без наслеђивања и без измене изворног кода. За разлику од extension functions, својства-проширења не могу чувати стање — она се декларишу само са гетером и опционално сетером, јер немају backing field. Према Kotlin Documentation, 2025, extension properties се компилирају у статичке методе getter и setter са receiver-ом као првим параметром.

Главно

  • Extension property — својство са receiver type, доступно кроз синтаксу својстава Kotlin-а
  • Нема backing field — extension property не може чувати стање, само да израчунава
  • Гетер је обавезан, сетер је опционалан — декларишу се као обичне extension функције
  • Nullable типови су подржани: receiver може бити nullable са провером унутар
  • Mutable extension property — само при декларисању var са гетером и сетером

Шта је extension property у Kotlin-у?

extension property — је синтаксна конструкција Kotlin-а која додаје својство постојећем типу без мењања његове декларације. Својство се декларише са наводом receiver-типа и обавезно садржи гетер. Кључна разлика у односу на обична својства — непостојање backing field: extension property не може да чува податке, већ их само израчунава на основу receiver-објекта.

Према Kotlin Foundation Survey (2024), extension properties су мање популарне од extension functions — око 45% програмера их редовно користи. То је због ограничења непостојања стања, што сужава област примене. Ипак, за израчуната својства која су логички везана за тип, extension properties су најконцизнија опција.

Extension properties се компилирају у пар статичких метода getter и setter. На нивоу бајт-кода нема разлике између позива extension property и extension function — оба постају статичке методе са receiver параметром. Према подацима JetBrains (Kotlin Docs, 2025), надокретје је потпуно одсутан.

Користите extension properties за кратке израчунате вредности које треба да изгледају као својства, а не као позиви метода — то побољшава читљивост кода и поштује принцип једнаког приступа.

Синтакса extension property: val и var

За декларисање extension property користи се синтакса слична обичном својству, али са префиксом receiver-типа. val декларише read-only extension property са обавезним гетером, var — mutable са гетером и опционалним сетером.

kotlin
// Read-only extension property
val String.isEmail: Boolean
    get() = this.contains("@") && this.contains(".")

// Poziv
val valid = "test@test.com".isEmail

Обратите пажња: extension property се позива без заграда — str.isEmail, а не str.isEmail(). То је кључна разлика између extension property и extension function: property изгледа као поље, иако се заправо израчунава кроз гетер.

Generic extension property

Extension properties могу бити опште — receiver може да користи generic параметре. То омогућује стварање универзалних својстава која раде са било којим типом колекције.

kotlin
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 ради за било који тип T, враћајући други елемент листе или null ако има мање од два елемента. То је типичан примјер где је extension property прикладнија од функције — приступ изгледа као читање поља.

Зашто extension property не може да чува стање

Extension property не може имати backing field јер се не додаје у метаподатке класе — постоји само као пар статичких функција getter/setter. Backing field (кључна реч field у Kotlin-у) — је унутрашње поље класе које чува вредност својства. Extension property нема приступ унутрашњој структури класе.

kotlin
// ❌ GREŠKA: extension property ne može imati backing field
var String.cachedValue: String
    get() = "computed"
    set(value) {
        field = value // polje nije dostupno!
    }

// ✅ ISPRAVNO: koristite spoljašnje skladište
val cache = MutableMap<String, String>()

var String.cachedValue: String
    get() = cache[this] ?: ""
    set(value) { cache[this] = value }

Спољашњи Map у примјеру решава проблем складиштења, али ствара други — цурење меморије. Вредности добијене кроз extension property живе у Map-у заувек ако се не очисте. То ограничење чини extension properties непогодним за кеширање или чување привремених података.

За кеширање се препоручује коришћење WeakHashMap или механизама са аутоматским чишћењем. JetBrains препоручује да се избегава коришћење var extension properties са спољашњим складиштем у производном коду без пажљивог управљања животним циклусом.

Extension property наспрам extension function: када шта одабрати

Избор између extension property и extension function зависи од семантике: својство описује карактеристику објекта, а функција — радњу. Принцип једнаког приступа (Uniform Access Principle) каже: клијент не треба да зна да ли се вредност израчунава или чува. Ако се вредност може представити као карактеристика (дужина, величина, статус) — користите property.

КритеријумExtension propertyExtension function
ПозивБез заграда: obj.propertyСа заградама: obj.function()
СемантикаКарактеристика, атрибутРадња, операција
Backing fieldНије подржанНије примењиво
ПараметриСамо getter/setterБило који параметри
ПерформансеИсто (статичка метода)Исто (статичка метода)
Примјерtext.lengthtext.isEmail()

Правило је једноставно: ако операција прихвата параметре — користите extension function. Ако је то једноставна израчуната вредност без параметара — extension property. Према подацима Android Architecture Guide (Google, 2025), предност треба дати extension properties за приступ подацима и extension functions за операције са нуспоредним ефектима.

Mutable extension property са var и сетером

Extension property са кључном речју var подржава сетер, али без могућности чувања вредности — сетер обично извршава нуспоредну радњу или чува податке у спољашњем складишту. Синтакса је аналогна mutable својствима класа.

kotlin
// Mutable extension property sa setterom
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 — класичан примјер из документације Kotlin-а. Getter враћа последњи знак StringBuilder-а, setter га замењује новом вредношћу. Обратите пажња: стање се чува у самом StringBuilder-у (кроз setCharAt), а не у одвојеном пољу — то је исправно коришћење extension property.

Практични примјери extension properties

У реалним пројектима extension properties се најчешче користе за поједностављивање приступа подацима колекција, израчунавање величина или статуса UI елемената и креирање погодног API-ја над постојећим класама. Стандардна библиотека Kotlin активно користи овај механизам: size, indices, lastIndex за колекције — то су extension properties.

kotlin
// Extension properties za kolekcije
val List<Int>.sumFast: Int
    get() = fold(0) { acc, i -> acc + i }

val String.half: String
    get() = this.substring(0, length / 2)

// Extension property za Android View
val View.isVisible: Boolean
    get() = visibility == View.VISIBLE

// Null provera putem sigurnog receivera
val String?.isNullOrBlank: Boolean
    get() = this == null || this.isBlank()

Extension property isVisible за View — примјер који сваки Android програмер треба да зна. Уместо view.visibility == View.VISIBLE може се писати view.isVisible. То је не само краће, већ се чита као природан језик: „ако је прозор видљив“. Упркос једноставности, оваква својства значајно побољшавају читљивост кода.

Често постављана питања

Може ли се декларисати extension property за companion object?

Не, extension properties не могу бити декларисане за companion object или object declaration. Механизам extension се примењује само на класе, интерфејсе и nullable типове. За object користите обичне функције највишег нивоа.

По чему се extension property разликује од inline својства?

Inline својство (са модификатором inline) — механизам Kotlin-а за позивање гетера/сетера без креирања објекта-својства. Extension property се увек компилира у статичку методу, а inline својство — у позив без овојница. Оне решавају различите задатке: extension property додаје својство постојећем типу, inline оптимизује позиве сопствених својстава.

Да ли extension property подржава анотације?

Да, extension property може да садржи анотације, али само на нивоу декларације. Не могу се анотирати одвојено getter или setter extension property — за разлику од обичних својстава класе. Примјер: @JvmName(„getIsValid“) val String.isValid get() = true.

Може ли се користити extension property са companion object класе?

Не, extension properties се не могу декларисати са companion object као receiver. То је ограничење језика — extension property ради само са инстанцама типова, а companion object је статички контекст. Користите extension функције највишег нивоа или константе.

Да ли extension property утиче на величину APK-а?

Минимално. Свака extension property додаје једну статичку методу getter (и опционално setter) у компилирани бајт-код. За поређење: креирање класе овојнице са истим својством додаје целу класу. Extension properties — лакши приступ проширењу функционалности.

Резиме

  • Extension property — израчунато својство за постојећи тип без наслеђивања
  • Нема backing field — стање се не чува, само се израчунава кроз getter
  • var са сетером — могуће, али захтева спољашњи склад за упис података
  • Синтакса — val/var са receiver-типом и обавезним getter-ом
  • Перформансе — нулти надокретја, компилира се у статичку методу
  • Примена — израчунате карактеристике: дужина, статус, величина, провере
  • Ограничење — не погодно за чување стања, кеширање без управљања меморијом

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође