Extensiefunctie in Kotlin: wat is het, syntax en toepassing

Auteur: IT Sectr Gepubliceerd: 2026-06-21 Leestijd: 9 min

extensiefunctie — Kotlin-mechanisme waarmee nieuwe methoden aan bestaande klassen kunnen worden toegevoegd zonder overerving en zonder wijziging van de broncode. De functie wordt gedeclareerd met een prefix in de vorm van een ontvangertype en wordt aangeroepen als een gewone methode van dit type. Volgens Kotlin Documentation, 2025 worden extensiefuncties gecompileerd naar statische methoden met de eerste parameter-ontvanger, wat nul overhead garandeert in runtime vergeleken met gewone aanroepen.

Belangrijkste

  • Extensiefunctie — methode met ontvangertype, aangeroepen als klassenlid zonder overerving
  • Ontvangertype wordt aangegeven met een punt voor de functienaam: fun Type.method()
  • Statische dispatch — extensiefunctie is niet virtueel, wordt aangeroepen op basis van het type variabele
  • Import is verplicht: extensiefuncties zijn geen klassenleden en vereisen import
  • Klassenleden hebben prioriteit: als de methode overeenkomt, wordt het klassenlid aangeroepen, niet de extensie

Wat is een extensiefunctie in Kotlin?

Een extensiefunctie is een functie die buiten de klasse wordt gedeclareerd, maar als zijn methode wordt aangeroepen. Het accepteert een ontvangertype waaraan een nieuwe methode wordt toegevoegd. Binnen de functie verwijst het sleutelwoord this naar het exemplaar van het ontvangertype. Deze aanpak maakt het mogelijk om final-klassen, klassen van externe bibliotheken en zelfs primitieve typen uit te breiden zonder wrappers te maken.

In tegenstelling tot Java, waar het toevoegen van een methode aan een bestaande klasse ofwel overerving ofwel een statische hulpklasse vereist, biedt Kotlin een elegante oplossing zonder boilerplate. Volgens gegevens van het Kotlin Foundation-onderzoek (2024) behoren extensiefuncties tot de vijf meest gebruikte taalfuncties — 78% van de Kotlin-ontwikkelaars gebruikt ze in het dagelijks werk.

De Kotlin-compiler vertaalt de extensiefunctie naar een statische methode, waarbij het ontvangerexemplaar als eerste argument wordt doorgegeven. Dit betekent dat extensiefuncties de bytecode van de doelklasse niet wijzigen en inkapseling niet schenden — alleen openbare velden en methoden van de ontvanger zijn toegankelijk.

Gebruik extensiefuncties om schone hulpfuncties te schrijven die logisch gebonden zijn aan een specifiek type, maar niet aan de broncode kunnen worden toegevoegd.

Syntax van extensiefunctie: declaratie en aanroep

De basissyntax van een extensiefunctie: naam van het ontvangertype, punt, functienaam, dan parameters en retourtype. Binnen de functie is de ontvanger toegankelijk via this.

kotlin
// Extensiefunctie voor String
fun String.isEmail(): Boolean {
    return this.contains("@") && this.contains(".")
}

// Aangeroepen als gewone String-methode
val result = "user@example.com".isEmail() // true

In dit voorbeeld wordt isEmail() beschikbaar voor alle strings. Binnen de functie is this de string zelf waarop de methode wordt aangeroepen. Kotlin staat toe this in de meeste gevallen weg te laten — je kunt gewoon contains("@") schrijven in plaats van this.contains("@").

Extensiefunctie met parameters

Extensiefuncties kunnen extra parameters accepteren en waarden van elk type retourneren. Dit maakt ze volwaardige functies, niet alleen syntaxissuiker.

kotlin
fun List<Int>.defaultIfEmpty(default: Int): List<Int> {
    if (this.isEmpty()) return listOf(default)
    return this
}

val populated = listOf(1, 2).defaultIfEmpty(0)
val empty = listOf<Int>().defaultIfEmpty(0)

De parameter default bepaalt de waarde die voor een lege lijst wordt geretourneerd. Een extensiefunctie kan generic zijn — het type List is gegeneraliseerd, hoewel in het voorbeeld een concrete List wordt gebruikt.

Statische dispatch en ontvanger

Extensiefuncties in Kotlin gebruiken statische dispatch, niet virtuele. Dit is het belangrijkste verschil met gewone klassenmethoden. Welke extensiefunctie wordt aangeroepen, wordt in de compilatiefase bepaald op basis van het statische type van de variabele, niet op basis van het werkelijke type in runtime.

kotlin
open class Animal
class Dog : Animal()

fun Animal.speak() = "Diergeluid"
fun Dog.speak() = "Blaf"

fun test() {
    val animal: Animal = Dog()
    println(animal.speak()) // „Diergeluid” — statisch type Animal

    val dog: Dog = Dog()
    println(dog.speak()) // „Blaf” — statisch type Dog
}

Hoewel de variabele animal naar een Dog-exemplaar verwijst, wordt de extensiefunctie voor Animal aangeroepen, omdat het statische type van de variabele Animal is. Als speak() een virtuele klassemethode was, zou Dog.speak() zijn aangeroepen. Deze eigenschap is belangrijk om in overweging te nemen bij het ontwerpen van API's op basis van extensiefuncties.

Import en zichtbaarheidsbereik van extensiefuncties

Extensiefuncties zijn geen klassenleden — het zijn gewone functies die import vereisen voor gebruik in een ander bestand. Kotlin biedt twee importvarianten: op functienaam of met hernoeming.

kotlin
// Import op naam
import com.example.extensions.isEmail

// Import met alias (om conflicten op te lossen)
import com.example.extensions.isEmail as isValidEmail

// Aanroep na import
val valid = "test@test.com".isEmail()

Hernoeming via as is nuttig bij naamconflicten — bijvoorbeeld als twee bibliotheken een extensiefunctie met dezelfde naam voor hetzelfde type bieden. In dit geval kan men een ervan onder een andere naam importeren en via de nieuwe naam aanroepen.

Zichtbaarheidsbereik

Extensiefuncties kunnen op verschillende niveaus worden gedeclareerd:

NiveauZichtbaarheidVoorbeeld
Top-levelHele project na importfun String.isEmail()
Member extensionBinnen de eigenaarklasseclass A { fun B.ext() }
LocalBinnen de functiefun test() { fun String.ext() }

Member extension functions — een speciaal geval waarbij de extensiefunctie binnen een andere klasse wordt gedeclareerd. In dit geval zijn binnen de extensiefunctie zowel de ontvanger (this van de functie) als de leden van de externe klasse toegankelijk.

Prioriteit van klassenleden boven extensies

Als de klasse een methode heeft met dezelfde handtekening als de extensiefunctie, wordt altijd het klassenlid aangeroepen. Een extensiefunctie overschrijft nooit de klassemethode — dit is een architectonische beslissing om accidentele overschrijvingen te voorkomen.

kotlin
class User {
    fun greet() = "Hallo vanuit klasse"
}

fun User.greet() = "Hello from extension"

fun main() {
    val user = User()
    println(user.greet()) // „Hallo vanuit klasse”
}

Zelfs als de extensiefunctie later wordt gedefinieerd en dezelfde handtekening heeft, kiest de compiler de klassemethode. De Kotlin-compiler geeft een waarschuwing bij het detecteren van een dergelijke situatie. De enige manier om een extensiefunctie aan te roepen in aanwezigheid van een klassemethode is door deze als een gewone functie aan te spreken: greet(user).

Praktische voorbeelden van extensiefuncties

In Android-ontwikkeling zijn extensiefuncties een standaardinstrument geworden voor het werken met View, Context en fragmenten. De Android KTX-bibliotheek is gebouwd op extensiefuncties en biedt handige wrappers voor de Android API.

kotlin
// Extensiefunctie voor werken met View
fun View.show() {
    visibility = View.VISIBLE
}

fun View.hide() {
    visibility = View.GONE
}

// Extensiefunctie voor Context — toast
fun Context.toast(message: String) {
    Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}

// Extensiefunctie als DSL-bouwer
fun String.colorFormat(color: String): String =
    "$color$this\u001b[0m"

De extensiefunctie toast() maakt Context-afhankelijke aanroepen beknopt: in plaats van Toast.makeText(context, message, length).show() te schrijven, volstaat context.toast("Tekst"). Dit vermindert boilerplate en maakt de code leesbaarder.

Veelgestelde vragen

Kan een extensiefunctie worden overschreven in een subklasse?

Nee, extensiefuncties gebruiken statische dispatch. Als u een extensiefunctie voor de basisklasse en dezelfde voor de subklasse declareert, welke wordt aangeroepen, wordt bepaald door het statische type van de variabele in de compilatiefase, niet door het werkelijke type in runtime.

Hoe werken extensiefuncties met nullable-typen?

U kunt extensiefuncties declareren voor nullable ontvangertypen: fun String?.isNullOrEmail(). Binnen zo'n functie kan this null zijn, daarom moet u veilige aanroepoperators of expliciete null-controle gebruiken.

Hebben extensiefuncties prestatie-overhead?

Nee, extensiefuncties worden gecompileerd naar statische methoden. Op bytecode-niveau is de aanroep van een extensiefunctie identiek aan de aanroep van een statische methode met de eerste parameter-ontvanger. Geen reflectie of dynamische dispatch.

Kan men een extensie-eigenschap voor een klasse declareren?

Ja, extensie-eigenschappen werken vergelijkbaar met extensiefuncties, maar kunnen geen status opslaan — alleen getter en setter. Bijvoorbeeld: val List<Int>.sum get() = reduce(Int::plus). Ze worden ook gecompileerd naar statische getter/setter-methoden.

Waarin verschillen extensiefuncties van methoden in Java-hulpklassen?

In Java schrijft u StringUtils.isEmail(str), in Kotlin — str.isEmail(). Het verschil zit niet alleen in de syntax: extensiefuncties ondersteunen automatisch aanvullen in de IDE, verbeteren de leesbaarheid van aanroepketens en stellen de IDE in staat relevante functies voor een specifiek type voor te stellen. In Java bestaan dergelijke mogelijkheden niet.

Samenvatting

  • Extensiefunctie — methode met ontvangertype, aangeroepen als klassenlid zonder overerving
  • Statische dispatch — functie selecteren op basis van statisch type, niet runtimetype
  • Nul overhead — gecompileerd naar statische methode met ontvanger als eerste parameter
  • Import verplicht voor gebruik in andere bestanden, alias mogelijk via as
  • Klassenleden hebben prioriteit boven extensiefuncties met dezelfde handtekening
  • Member extensions — binnen de klasse gedeclareerde extensies, hebben toegang tot zijn leden
  • Praktische toepassing — hulpprogramma's voor String, View, Context, collecties en DSL-bouw

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook