extension property — ein Kotlin-Mechanismus, der das Hinzufügen neuer Eigenschaften zu bestehenden Klassen ohne Vererbung und ohne Änderung des Quellcodes ermöglicht. Im Gegensatz zu extension functions können extension properties keinen Zustand speichern — sie werden nur mit einem Getter und optional einem Setter deklariert, da sie kein backing field haben. Laut Kotlin Documentation, 2025 werden extension properties in statische Getter- und Setter-Methoden mit dem Receiver als erstem Parameter kompiliert.
Wichtige Punkte
Eine extension property ist ein syntaktisches Konstrukt in Kotlin, das einem bestehenden Typ eine Eigenschaft hinzufügt, ohne seine Deklaration zu ändern. Die Eigenschaft wird mit einem Receiver-Typ deklariert und muss einen Getter enthalten. Der Hauptunterschied zu normalen Eigenschaften ist das Fehlen eines backing field: eine extension property kann keine Daten speichern, sondern nur basierend auf dem Receiver-Objekt berechnen.
Laut Kotlin Foundation Survey (2024) sind extension properties weniger beliebt als extension functions — etwa 45% der Entwickler nutzen sie regelmäßig. Dies liegt an der Einschränkung, keinen Zustand zu haben, was den Anwendungsbereich einengt. Dennoch sind extension properties für berechnete Eigenschaften, die logisch an einen Typ gebunden sind, die prägnanteste Option.
Extension properties werden in ein Paar statischer Getter- und Setter-Methoden kompiliert. Auf Bytecode-Ebene gibt es keinen Unterschied zwischen dem Aufruf einer extension property und dem Aufruf einer extension function — beide werden zu statischen Methoden mit einem Receiver-Parameter. Laut JetBrains (Kotlin Docs, 2025) gibt es überhaupt keinen Overhead.
Verwenden Sie extension properties für kurze berechnete Werte, die wie Eigenschaften und nicht wie Methodenaufrufe aussehen sollen — dies verbessert die Lesbarkeit des Codes und befolgt das Prinzip des einheitlichen Zugriffs.
Um eine extension property zu deklarieren, verwenden Sie eine ähnliche Syntax wie bei einer normalen Eigenschaft, jedoch mit dem Präfix des Receiver-Typs. val deklariert eine schreibgeschützte extension property mit einem obligatorischen Getter, var deklariert eine mutable mit einem Getter und einem optionalen Setter.
// Schreibgeschützte extension property
val String.isEmail: Boolean
get() = this.contains("@") && this.contains(".")
// Aufruf
val valid = "test@test.com".isEmail
Hinweis: Eine extension property wird ohne Klammern aufgerufen — str.isEmail, nicht str.isEmail(). Dies ist der Hauptunterschied zwischen einer extension property und einer extension function: Eine Eigenschaft sieht wie ein Feld aus, obwohl sie tatsächlich über einen Getter berechnet wird.
Extension properties können generisch sein — der Receiver kann generische Typparameter verwenden. Dies ermöglicht die Erstellung universeller Eigenschaften, die mit jedem Sammlungstyp funktionieren.
val List<T>.secondOrNull: T?
get() = if (size >= 2) this[1] else null
val items = listOf("a", "b", "c")
val second = items.secondOrNull // "b"
Die Eigenschaft secondOrNull funktioniert für jeden Typ T und gibt das zweite Element der Liste zurück oder null, wenn weniger als zwei Elemente vorhanden sind. Dies ist ein typisches Beispiel, bei dem eine extension property angemessener ist als eine Funktion — der Zugriff sieht wie das Lesen eines Feldes aus.
Eine extension property kann kein backing field haben, da sie nicht zu den Metadaten der Klasse hinzugefügt wird — sie existiert nur als Paar statischer Getter/Setter-Funktionen. Backing field (das Schlüsselwort field in Kotlin) ist ein internes Feld der Klasse, das den Eigenschaftswert speichert. Eine extension property hat keinen Zugriff auf die interne Struktur der Klasse.
// ❌ FEHLER: extension property kann kein backing field haben
var String.cachedValue: String
get() = "computed"
set(value) {
field = value // Feld ist nicht zugänglich!
}
// ✅ RICHTIG: externen Speicher verwenden
val cache = MutableMap<String, String>()
var String.cachedValue: String
get() = cache[this] ?: ""
set(value) { cache[this] = value }
Eine externe Map im Beispiel löst das Speicherproblem, erzeugt aber ein anderes — ein Speicherleck. Über eine extension property erhaltene Werte leben für immer in der Map, wenn sie nicht bereinigt werden. Diese Einschränkung macht extension properties ungeeignet für Caching oder die Speicherung temporärer Daten.
Für Caching wird die Verwendung einer WeakHashMap oder Mechanismen mit automatischer Bereinigung empfohlen. JetBrains empfiehlt, die Verwendung von var extension properties mit externem Speicher in Produktionscode ohne sorgfältiges Lebenszyklusmanagement zu vermeiden.
Die Wahl zwischen einer extension property und einer extension function hängt von der Semantik ab: Eine Eigenschaft beschreibt eine Eigenschaft eines Objekts, während eine Funktion eine Aktion beschreibt. Das Prinzip des einheitlichen Zugriffs besagt: Der Client soll nicht wissen, ob ein Wert berechnet oder gespeichert wird. Wenn der Wert als Eigenschaft (Länge, Größe, Status) dargestellt werden kann — verwenden Sie eine Eigenschaft.
| Kriterium | Extension property | Extension function |
|---|---|---|
| Aufruf | Ohne Klammern: obj.property | Mit Klammern: obj.function() |
| Semantik | Eigenschaft, Attribut | Aktion, Operation |
| Backing field | Nicht unterstützt | Nicht zutreffend |
| Parameter | Nur Getter/Setter | Beliebige Parameter |
| Leistung | Gleich (statische Methode) | Gleich (statische Methode) |
| Beispiel | text.length | text.isEmail() |
Die Regel ist einfach: Wenn die Operation Parameter akzeptiert — verwenden Sie eine extension function. Wenn es sich um einen einfachen berechneten Wert ohne Parameter handelt — verwenden Sie eine extension property. Laut Android Architecture Guide (Google, 2025) sollten extension properties für den Datenzugriff und extension functions für Operationen mit Nebeneffekten bevorzugt werden.
Eine extension property mit dem Schlüsselwort var unterstützt einen Setter, jedoch ohne die Möglichkeit, einen Wert zu speichern — der Setter führt normalerweise einen Nebeneffekt aus oder speichert Daten in einem externen Speicher. Die Syntax ähnelt den mutablen Klasseneigenschaften.
// Mutable extension property mit 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!
Die Eigenschaft lastChar ist ein klassisches Beispiel aus der Kotlin-Dokumentation. Der Getter gibt das letzte Zeichen von StringBuilder zurück, der Setter ersetzt es durch einen neuen Wert. Hinweis: Der Zustand wird im StringBuilder selbst (über setCharAt) gespeichert, nicht in einem separaten Feld — dies ist eine korrekte Verwendung einer extension property.
In realen Projekten werden extension properties am häufigsten verwendet, um den Zugriff auf Sammlungsdaten zu vereinfachen, Größen oder Status von UI-Elementen zu berechnen und eine bequeme API über bestehenden Klassen zu erstellen. Die Kotlin-Standardbibliothek nutzt diesen Mechanismus aktiv: size, indices, lastIndex für Sammlungen sind extension properties.
// Extension properties für Sammlungen
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-Prüfung über sicheren Receiver
val String?.isNullOrBlank: Boolean
get() = this == null || this.isBlank()
Die extension property isVisible für View ist ein Beispiel, das jeder Android-Entwickler kennen sollte. Statt view.visibility == View.VISIBLE können Sie view.isVisible schreiben. Dies ist nicht nur kürzer, sondern liest sich auch wie natürliche Sprache: „Wenn die View sichtbar ist“. Trotz ihrer Einfachheit verbessern solche Eigenschaften die Lesbarkeit des Codes erheblich.
Häufig gestellte Fragen
Nein, extension properties können nicht für ein companion object oder eine object declaration deklariert werden. Der Erweiterungsmechanismus gilt nur für Klassen, Schnittstellen und nullable Typen. Für object verwenden Sie normale Top-Level-Funktionen.
Eine inline property (mit dem inline-Modifikator) ist ein Kotlin-Mechanismus zum Aufrufen eines Getters/Setters ohne Erstellung eines Eigenschaftsobjekts. Eine extension property wird immer in eine statische Methode kompiliert, während eine inline property in einen Aufruf ohne Wrapper kompiliert wird. Sie lösen unterschiedliche Probleme: Eine extension property fügt einem bestehenden Typ eine Eigenschaft hinzu, während inline Aufrufe eigener Eigenschaften optimiert.
Ja, eine extension property kann Annotationen haben, jedoch nur auf Deklarationsebene. Im Gegensatz zu normalen Klasseneigenschaften können Getter oder Setter einer extension property nicht separat annotiert werden. Beispiel: @JvmName(„getIsValid“) val String.isValid get() = true.
Nein, extension properties können nicht mit einem companion object als Receiver deklariert werden. Dies ist eine Spracheinschränkung — eine extension property funktioniert nur mit Typinstanzen, während ein companion object ein statischer Kontext ist. Verwenden Sie Top-Level-extension functions oder Konstanten.
Minimal. Jede extension property fügt eine statische Getter-Methode (und optional einen Setter) zum kompilierten Bytecode hinzu. Zum Vergleich: Das Erstellen einer Wrapper-Klasse mit derselben Eigenschaft fügt eine ganze Klasse hinzu. Extension properties sind ein leichterer Ansatz zur Erweiterung der Funktionalität.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch