Extension properties zijn uitbreidingen voor klassen die het mogelijk maken om getters en setters toe te voegen zonder de mogelijkheid om een toestand (backing field) toe te voegen. In Java is deze mogelijkheid er niet, en de analoge oplossing is het schrijven van utiliteitsmethoden. Historisch gezien moest er voor het toevoegen van functionaliteit gebruik worden gemaakt van statische methoden of Wrapper-objecten.
Probleem: in externe klassen ontbreken vaak de benodigde properties. Je wilt de klasse beknopt en veilig uitbreiden, zonder de encapsulatie te verstoren.
Oplossing: in Kotlin kun je een extension property declareren die eruitziet als een gewone property, maar is geïmplementeerd als functies. Dit maakt het mogelijk om types uit te breiden waarvoor we geen toegang hebben tot de broncode, op een handige manier.
Codevoorbeeld:
val String.firstChar: Char get() = this[0] println("Kotlin".firstChar) // K
Belangrijkste kenmerken:
Kan ik een backing field (toestand) toevoegen aan een extension property?
Nee, een extension property berekent alleen de waarde on-the-fly en kan geen toestand opslaan.
Kunnen extension properties eigenschappen in afgeleide klassen overschrijven?
Nee, extension properties (net als extension functies) zijn in wezen statisch: ze kunnen niet worden overschreven of virtueel zijn.
Hoe wordt een extension property gecompileerd, en waarom is het geen syntactische analoog van een gewone property?
Een extension property wordt in feite gecompileerd naar een statische getter (en/of setter) functie. Ze zijn niet opgenomen in de class entity en zijn alleen zichtbaar in de context van het bestand waarin ze zijn gedeclareerd.
Negatieve case
Een ontwikkelaar probeerde een extension property toe te voegen voor het opslaan van de toestand "bezocht" in de standaard Android View:
var View.isVisited: Boolean get() = ... set(value) { ... } // Fout: geen opslag
Voordelen:
Nadelen:
Positieve case
Een extension property is geïmplementeerd voor String om een uitgebreide opmaak te krijgen:
val String.asTitle: String get() = this.replaceFirstChar { it.uppercase() }
Voordelen:
Nadelen: