Extension property în Kotlin — ce este, sintaxa și aplicarea

Autor: IT Sectr Publicat: 2026-06-21 Timp de citire: 8 min

extension property — un mecanism Kotlin care permite adăugarea de noi proprietăți la clasele existente fără moștenire și fără modificarea codului sursă. Spre deosebire de extension functions, proprietățile-extensie nu pot starea stare — ele sunt declarate doar cu getter și opțional setter, deoarece nu au backing field. Potrivit Kotlin Documentation, 2025, extension properties sunt compilate în metode statice getter și setter cu receiver ca prim parametru.

Principalele puncte

  • Extension property — proprietate cu receiver type, accesibilă prin sintaxa proprietăților Kotlin
  • Fără backing field — extension property nu poate starea stare, doar calcula
  • Getter obligatoriu, setter opțional — declarate ca extension functions obișnuite
  • Tipurile nullable sunt suportate: receiver poate fi nullable cu verificare internă
  • Mutable extension property — doar la declararea var cu getter și setter

Ce este extension property în Kotlin?

extension property — este o construcție sintactică Kotlin care adaugă o proprietate la un tip existent fără a modifica declarația acestuia. Proprietatea este declarată cu specificarea tipului receiver și conține obligatoriu un getter. Diferența cheie față de proprietățile obișnuite — lipsa backing field: extension property nu poate starea date, ci doar le calculează pe baza obiectului receiver.

Potrivit Kotlin Foundation Survey (2024), extension properties sunt mai puțin populare decât extension functions — aproximativ 45% dintre dezvoltatori le folosesc regulat. Acest lucru se datorează limitării lipsei de stare, ceea ce restrânge domeniul de aplicare. Cu toate acestea, pentru proprietățile calculate logic legate de tip, extension properties sunt cea mai concisă opțiune.

Extension properties sunt compilate în perechi de metode statice getter și setter. La nivel de bytecode, nu există diferență între apelul unei extension property și al unei extension function — ambele devin metode statice cu parametrul receiver. Potrivit datelor JetBrains (Kotlin Docs, 2025), overhead-ul este complet absent.

Folosiți extension properties pentru valori calculate scurte care ar trebui să arate ca proprietăți, nu ca apeluri de metode — acest lucru îmbunătățește lizibilitatea codului și respectă principiul accesului uniform.

Sintaxa extension property: val și var

Pentru declararea unei extension property se folosește o sintaxă similară cu o proprietate obișnuită, dar cu prefixul tipului receiver. val declară o read-only extension property cu getter obligatoriu, var — mutable cu getter și setter opțional.

kotlin
// Extension property numai pentru citire
val String.isEmail: Boolean
    get() = this.contains("@") && this.contains(".")

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

Rețineți: extension property este apelată fără paranteze — str.isEmail, nu str.isEmail(). Aceasta este diferența cheie între extension property și extension function: property arată ca un câmp, deși de fapt este calculată prin getter.

Generic extension property

Extension properties pot fi generalizate — receiver poate folosi parametri generic. Acest lucru permite crearea de proprietăți universale care funcționează cu orice tip de colecție.

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"

Proprietatea secondOrNull funcționează pentru orice tip T, returnând al doilea element al listei sau null dacă sunt mai puține de două elemente. Acesta este un exemplu tipic unde extension property este mai potrivită decât o funcție — accesul arată ca o citire a unui câmp.

De ce extension property nu poate starea stare

Extension property nu poate avea backing field pentru că nu este adăugată în metadatele clasei — există doar ca o pereche de funcții statice getter/setter. Backing field (cuvântul cheie field în Kotlin) — este câmpul intern al clasei care stochează valoarea proprietății. Extension property nu are acces la structura internă a clasei.

kotlin
// ❌ EROARE: extension property nu poate avea un backing field
var String.cachedValue: String
    get() = "computed"
    set(value) {
        field = value // câmpul nu este accesibil!
    }

// ✅ CORECT: folosiți stocare externă
val cache = MutableMap<String, String>()

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

Map-ul extern din exemplu rezolvă problema stocării, dar creează alta — scurgerea de memorie. Valorile obținute prin extension property trăiesc în Map pentru totdeauna dacă nu sunt curățate. Această limitare face extension properties nepotrivite pentru cache sau stocarea datelor temporare.

Pentru cache, se recomandă utilizarea WeakHashMap sau a mecanismelor cu curățare automată. JetBrains recomandă evitarea utilizării var extension properties cu stocare externă în codul de producție fără o gestionare atentă a ciclului de viață.

Extension property vs extension function: când să alegeți

Alegerea între extension property și extension function depinde de semantică: proprietatea descrie o caracteristică a obiectului, iar funcția — o acțiune. Principiul accesului uniform (Uniform Access Principle) spune: clientul nu trebuie să știe dacă valoarea este calculată sau stocată. Dacă valoarea poate fi prezentată ca o caracteristică (lungime, dimensiune, stare) — folosiți property.

CriteriuExtension propertyExtension function
ApelFără paranteze: obj.propertyCu paranteze: obj.function()
SemanticăCaracteristică, atributAcțiune, operație
Backing fieldNu este suportatNu se aplică
ParametriDoar getter/setterOrice parametri
PerformanțăLa fel (metodă statică)La fel (metodă statică)
Exemplutext.lengthtext.isEmail()

Regula este simplă: dacă operația acceptă parametri — folosiți extension function. Dacă este o valoare simplă calculată fără parametri — extension property. Potrivit Android Architecture Guide (Google, 2025), ar trebui să preferați extension properties pentru accesul la date și extension functions pentru operații cu efecte secundare.

Mutable extension property cu var și setter

Extension property cu cuvântul cheie var suportă setter, dar fără posibilitatea de a starea valoarea — setter-ul de obicei execută o acțiune secundară sau salvează date într-un depozit extern. Sintaxa este analogă proprietăților mutable ale claselor.

kotlin
// Mutable extension property cu 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!

Proprietatea lastChar — un exemplu clasic din documentația Kotlin. Getter returnează ultimul caracter al StringBuilder, setter îl înlocuiește cu o nouă valoare. Rețineți: starea este stocată în însuși StringBuilder (prin setCharAt), nu într-un câmp separat — aceasta este o utilizare corectă a extension property.

Exemple practice de extension properties

În proiecte reale, extension properties sunt cel mai des folosite pentru simplificarea accesului la datele colecțiilor, calcularea dimensiunilor sau stărilor elementelor UI și crearea de API-uri convenabile peste clasele existente. Biblioteca standard Kotlin folosește activ acest mecanism: size, indices, lastIndex pentru colecții — acestea sunt extension properties.

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

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

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

// Verificare null prin receiver sigur
val String?.isNullOrBlank: Boolean
    get() = this == null || this.isBlank()

Extension property isVisible pentru View — un exemplu pe care orice dezvoltator Android ar trebui să-l cunoască. În loc de view.visibility == View.VISIBLE se poate scrie view.isVisible. Nu doar că este mai scurt, dar se citește ca un limbaj natural: „dacă vizualizarea este vizibilă”. În ciuda simplității, astfel de proprietăți îmbunătățesc semnificativ lizibilitatea codului.

Întrebări frecvente

Se poate declara o extension property pentru companion object?

Nu, extension properties nu pot fi declarate pentru companion object sau object declaration. Mecanismul extension se aplică doar claselor, interfețelor și tipurilor nullable. Pentru object, folosiți funcții obișnuite de nivel superior.

Cu ce diferă extension property de o proprietate inline?

Proprietatea inline (cu modificatorul inline) — un mecanism Kotlin pentru apelarea getter-ului/setter-ului fără a crea un obiect-proprietate. Extension property este întotdeauna compilată într-o metodă statică, iar proprietatea inline — într-un apel fără îmbrăcare. Ele rezolvă sarcini diferite: extension property adaugă o proprietate la un tip existent, inline optimizează apelurile propriilor proprietăți.

Extension properties suportă adnotări?

Da, extension property poate conține adnotări, dar doar la nivelul declarației. Nu se pot adnota separat getter-ul sau setter-ul unei extension property — spre deosebire de proprietățile obișnuite ale clasei. Exemplu: @JvmName(“getIsValid”) val String.isValid get() = true.

Se poate folosi extension property cu companion object al clasei?

Nu, extension properties nu pot fi declarate cu companion object ca receiver. Aceasta este o limitare a limbajului — extension property funcționează doar cu instanțe ale tipurilor, iar companion object este un context static. Folosiți extension functions de nivel superior sau constante.

Extension property afectează dimensiunea APK-ului?

Minim. Fiecare extension property adaugă o metodă statică getter (și opțional setter) la bytecode-ul compilat. Pentru comparație: crearea unei clase-wrappler cu aceeași proprietate adaugă o clasă întreagă. Extension properties — o abordare mai ușoară pentru extinderea funcționalității.

Rezumat

  • Extension property — proprietate calculată pentru un tip existent fără moștenire
  • Fără backing field — starea nu este stocată, doar calculată prin getter
  • var cu setter — posibil, dar necesită stocare externă pentru scrierea datelor
  • Sintaxa — val/var cu tipul receiver și getter obligatoriu
  • Performanță — overhead zero, compilată în metodă statică
  • Aplicație — caracteristici calculate: lungime, stare, dimensiune, verificări
  • Limitare — nepotrivită pentru stocarea stării, cache fără gestionarea memoriei

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și