extension property — en Kotlin-mekanism som gör det möjligt att lägga till nya egenskaper till befintliga klasser utan arv och utan att ändra källkoden. Till skillnad från extension functions kan egenskapsutökningar inte lagra tillstånd — de deklareras endast med en getter och eventuellt en setter, eftersom de inte har något backing field. Enligt Kotlin Documentation, 2025 kompileras extension properties till statiska getter- och setter-metoder med receiver som första parameter.
Huvudpunkter
extension property — är en syntaktisk konstruktion i Kotlin som lägger till en egenskap till en befintlig typ utan att ändra dess deklaration. Egenskapen deklareras med angivelse av receiver-typen och innehåller obligatoriskt en getter. Den viktigaste skillnaden från vanliga egenskaper — avsaknaden av backing field: extension property kan inte lagra data, utan beräknar dem endast baserat på receiver-objektet.
Enligt Kotlin Foundation Survey (2024) är extension properties mindre populära än extension functions — cirka 45% av utvecklarna använder dem regelbundet. Detta beror på begränsningen av avsaknad av tillstånd, vilket begränsar tillämpningsområdet. Icke desto mindre, för beräknade egenskaper som är logiskt kopplade till typen, är extension properties det mest koncisa alternativet.
Extension properties kompileras till ett par statiska getter- och setter-metoder. På bytekodnivå finns det ingen skillnad mellan att anropa en extension property och en extension function — båda blir statiska metoder med receiver-parameter. Enligt data från JetBrains (Kotlin Docs, 2025) är overhead helt frånvarande.
Använd extension properties för korta beräknade värden som bör se ut som egenskaper, inte som metodanrop — detta förbättrar kodens läsbarhet och följer principen om enhetlig åtkomst.
För att deklarera en extension property används en syntax som liknar en vanlig egenskap, men med prefix av receiver-typen. val deklarerar en read-only extension property med obligatorisk getter, var — mutable med getter och valfri setter.
// Skrivskyddad extension property
val String.isEmail: Boolean
get() = this.contains("@") && this.contains(".")
// Anrop
val valid = "test@test.com".isEmail
Lägg märke till: extension property anropas utan parenteser — str.isEmail, inte str.isEmail(). Detta är den viktigaste skillnaden mellan extension property och extension function: property ser ut som ett fält, även om det i verkligheten beräknas via getter.
Extension properties kan vara generiska — receiver kan använda generiska parametrar. Detta gör det möjligt att skapa universella egenskaper som fungerar med vilken samlingstyp som helst.
val List<T>.secondOrNull: T?
get() = if (size >= 2) this[1] else null
val items = listOf("a", "b", "c")
val second = items.secondOrNull // "b"
Egenskapen secondOrNull fungerar för alla typer T och returnerar det andra elementet i listan eller null om det finns färre än två element. Detta är ett typiskt exempel där extension property är lämpligare än en funktion — åtkomsten ser ut som att läsa ett fält.
En extension property kan inte ha ett backing field eftersom den inte läggs till i klassens metadata — den finns endast som ett par statiska getter/setter-funktioner. Backing field (nyckelordet field i Kotlin) — är klassens interna fält som lagrar egenskapens värde. Extension property har inte tillgång till klassens interna struktur.
// ❌ FEL: extension property kan inte ha ett backing field
var String.cachedValue: String
get() = "computed"
set(value) {
field = value // fältet är inte tillgängligt!
}
// ✅ RÄTT: använd extern lagring
val cache = MutableMap<String, String>()
var String.cachedValue: String
get() = cache[this] ?: ""
set(value) { cache[this] = value }
Den externa Map i exemplet löser lagringsproblemet men skapar ett annat — minnesläcka. Värden som erhålls via extension property lever i Map för evigt om de inte rensas. Denna begränsning gör extension properties olämpliga för caching eller lagring av tillfälliga data.
För caching rekommenderas användning av WeakHashMap eller mekanismer med automatisk rensning. JetBrains rekommenderar att undvika användning av var extension properties med extern lagring i produktionskod utan noggrann livscykelhantering.
Valet mellan extension property och extension function beror på semantik: egenskapen beskriver en egenskap hos ett objekt, funktionen beskriver en handling. Principen om enhetlig åtkomst (Uniform Access Principle) säger: klienten bör inte veta om värdet beräknas eller lagras. Om värdet kan presenteras som en egenskap (längd, storlek, status) — använd property.
| Kriterium | Extension property | Extension function |
|---|---|---|
| Anrop | Utan parentes: obj.property | Med parentes: obj.function() |
| Semantik | Egenskap, attribut | Handling, operation |
| Backing field | Stöds inte | Ej tillämpligt |
| Parametrar | Endast getter/setter | Alla parametrar |
| Prestanda | Samma (statisk metod) | Samma (statisk metod) |
| Exempel | text.length | text.isEmail() |
Regeln är enkel: om operationen accepterar parametrar — använd extension function. Om det är ett enkelt beräknat värde utan parametrar — extension property. Enligt Android Architecture Guide (Google, 2025) bör extension properties föredras för dataåtkomst och extension functions för operationer med biverkningar.
Extension property med nyckelordet var stöder setter, men utan möjlighet att lagra värdet — settern utför vanligtvis en biverkning eller sparar data i en extern lagring. Syntaxen är analog med mutable egenskaper hos klasser.
// Mutable extension property med 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!
Egenskapen lastChar — ett klassiskt exempel från Kotlin-dokumentationen. Gettern returnerar det sista tecknet i StringBuilder, settern ersätter det med ett nytt värde. Lägg märke till: tillståndet lagras i själva StringBuilder (via setCharAt), inte i ett separat fält — detta är korrekt användning av extension property.
I verkliga projekt används extension properties oftast för att förenkla åtkomst till samlingsdata, beräkna storlekar eller status för UI-element och skapa bekväma API:er ovanpå befintliga klasser. Kotlins standardbibliotek använder aktivt denna mekanism: size, indices, lastIndex för samlingar — dessa är extension properties.
// Extension properties för samlingar
val List<Int>.sumFast: Int
get() = fold(0) { acc, i -> acc + i }
val String.half: String
get() = this.substring(0, length / 2)
// Extension property för Android View
val View.isVisible: Boolean
get() = visibility == View.VISIBLE
// Null-kontroll via säker receiver
val String?.isNullOrBlank: Boolean
get() = this == null || this.isBlank()
Extension property isVisible för View — ett exempel som varje Android-utvecklare bör känna till. Istället för view.visibility == View.VISIBLE kan man skriva view.isVisible. Det är inte bara kortare utan läses som naturligt språk: “om vyn är synlig”. Trots sin enkelhet förbättrar sådana egenskaper avsevärt kodens läsbarhet.
Vanliga frågor
Nej, extension properties kan inte deklareras för companion object eller object declaration. Extension-mekanismen gäller endast klasser, gränssnitt och nullable-typer. För object, använd vanliga funktioner på högsta nivå.
Inline-egenskap (med modifieraren inline) — en Kotlin-mekanism för att anropa getter/setter utan att skapa ett egenskapsobjekt. Extension property kompileras alltid till en statisk metod, medan inline-egenskap kompileras till ett anrop utan omslag. De löser olika uppgifter: extension property lägger till en egenskap till en befintlig typ, inline optimerar anrop av egna egenskaper.
Ja, extension property kan innehålla annoteringar, men endast på deklarationsnivå. Gettern eller settern för en extension property kan inte annoteras separat — till skillnad från vanliga klassegenskaper. Exempel: @JvmName(“getIsValid”) val String.isValid get() = true.
Nej, extension properties kan inte deklareras med companion object som receiver. Detta är en språkbegränsning — extension property fungerar endast med instanser av typer, och companion object är en statisk kontext. Använd extension functions på högsta nivå eller konstanter.
Minimalt. Varje extension property lägger till en statisk getter-metod (och valfri setter) i den kompilerade bytekoden. Som jämförelse: att skapa en wrapper-klass med samma egenskap lägger till en hel klass. Extension properties — ett lättare tillvägagångssätt för att utöka funktionalitet.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också