Scope functions — wat zijn het, soorten en toepassing in Kotlin

Auteur: IT Sectr Gepubliceerd: 2026-06-23 Leestijd: 8 min

Scope functions in Kotlin zijn vijf functies van de standaardbibliotheek (let, run, with, apply, also) die een codeblok uitvoeren in de context van een object. Ze verschillen in de manier van toegang tot het object (via it of this) en de retourwaarde (contextobject of resultaat van de lambda). Volgens Kotlin documentatie (2026) vermindert de juiste keuze van scope function de boilerplate-code met 25–40%. Scope functions helpen bij het schrijven van initialisatie, configuratie en transformaties van objecten in declaratieve stijl.

Belangrijkste punten

  • Scope functions — vijf Kotlin-functies (let, run, with, apply, also) voor het werken in de context van een object
  • Context via this — run, with, apply gebruiken this, waardoor methoden van het object direct kunnen worden aangeroepen
  • Context via it — let en also geven het object door als parameter it met expliciete naamgeving
  • Object retourneren — apply en also retourneren het contextobject voor het koppelen van aanroepen
  • Resultaat retourneren — let, run en with retourneren de laatste expressie van de lambda

Wat zijn scope functions?

Scope functions (bereikfuncties) — een set van vijf functies (let, run, with, apply, also) ingebouwd in de standaardbibliotheek van Kotlin. Elk van hen neemt een lambda en wijzigt tijdelijk het bereik zodat de code binnen de lambda wordt uitgevoerd in de context van een specifiek object. Dit voorkomt herhaling van de objectnaam bij meerdere aanroepen en groepeert gerelateerde bewerkingen in één blok.

Twee belangrijke kenmerken onderscheiden scope functions: de manier van toegang tot het contextobject (via this of via it) en de retourwaarde (het contextobject zelf of het resultaat van de lambda). Toegang via this maakt het object een impliciete ontvanger — methoden en eigenschappen worden zonder prefix aangeroepen. Toegang via it geeft het object door als expliciete parameter van de lambda. Het retourneren van het object maakt het bouwen van ketens mogelijk, het retourneren van het resultaat — het toewijzen van de getransformeerde waarde.

Historisch gezien verschenen scope functions als vervanging van het klassieke Builder-patroon en tijdelijke variabelen voor initialisatie. In plaats van het maken van een aparte builder-klasse schrijft de ontwikkelaar apply { eigenschap1 = ...; eigenschap2 = ... }. Dit vermindert de hoeveelheid code en maakt initialisatie leesbaarder. In het Kotlin-ecosysteem worden scope functions in alle frameworks en bibliotheken gebruikt als een standaard idioom van de taal.

Vergelijking van scope functions: this vs it, object vs resultaat

De keuze van de juiste scope function wordt bepaald door twee vragen: wilt u this of it gebruiken voor toegang tot het object, en wilt u het object zelf of het resultaat van de lambda retourneren. De combinatie van twee binaire kenmerken geeft vier mogelijke varianten, en with neemt een speciale plaats in als de enige functie die geen extensie is.

FunctieToegangRetourExtensie?Typisch scenario
letitresultaat lambdajaTransformatie, null-controle
runthisresultaat lambdajaBerekening met context
withthisresultaat lambdaneeGroeperen van aanroepen
applythiscontextobjectjaInitialisatie van eigenschappen
alsoitcontextobjectjaBijwerkingen, loggen

Voor configuratie van een object zonder het retourneren van een nieuwe waarde gebruikt u apply (toegang via this) of also (toegang via it). Voor het berekenen van een nieuwe waarde op basis van het object gebruikt u let (toegang via it) of run (toegang via this). Voor het groeperen van aanroepen zonder koppeling gebruikt u with. Het volgen van dit schema maakt de code voorspelbaar voor andere ontwikkelaars die bekend zijn met Kotlin.

apply en also: configuratie met object retourneren

apply — scope function die het contextobject retourneert en er toegang toe biedt via this. Het is het ideale hulpmiddel voor het initialiseren van eigenschappen van een object na creatie. Binnen het apply-blok kunnen eigenschappen worden ingesteld zonder herhaling van de objectnaam. De methode retourneert het object zelf, waardoor apply in ketens kan worden ingebouwd of in initialisatoren kan worden gebruikt.

kotlin
data class ServerConfig(
    var host: String = "localhost",
    var port: Int = 8080,
    var useTls: Boolean = false
)

val config = ServerConfig().apply {
    host = "api.example.com"
    port = 443
    useTls = true
}

In de listing configureert apply ServerConfig door rechtstreeks via this toegang te krijgen tot eigenschappen (this weggelaten). Zonder apply zou men config.host = ..., config.port = ... moeten schrijven — drie herhaalde verwijzingen naar dezelfde variabele. Het retourneren van het object maakt het mogelijk het configuratieresultaat op te slaan in val config. also geeft, in tegenstelling tot apply, het object door via it en is geschikt voor bijwerkingen.

kotlin
fun saveUser(user: User) {
    validate(user).also { result ->
        println("Validatieresultaat: $result")
    }
    val savedUser = user.also {
        log("Saving user ${it.id}")
        database.save(it)
    }
}

In het voorbeeld wordt also gebruikt voor loggen — door het originele object te retourneren, voert het een bijwerking uit (bericht weergeven) zonder het object te wijzigen. Dit is een keten: validate(user) retourneert User, also logt het resultaat en geeft de gebruiker door. also is ook handig voor het toevoegen van elementen aan verzamelingen of debuggen in het midden van een transformatieketen.

let en run: transformaties en berekeningen

let — scope function die het resultaat van de lambda retourneert en de context doorgeeft via it. Dit is de primaire functie voor null-veilige transformaties: als het object nullable is, voert de combinatie ?.let { } het blok alleen uit bij een niet-null waarde. let wordt ook gebruikt voor het beperken van het bereik van tijdelijke variabelen en map-achtige transformaties van het ene type naar het andere.

kotlin
fun findUser(id: Int): User?

val displayName = findUser(42)?.let { user ->
    "${user.name} (${user.email})"
} ?: "Unknown user"

// let met collectietransformatie
val numbers = listOf("1", "2", "3")
val parsed = numbers.firstOrNull()?.let {
    it.toIntOrNull()
} ?: 0

In het eerste voorbeeld wordt let aangeroepen via ?. — het blok wordt alleen uitgevoerd als findUser niet-null heeft geretourneerd. De lambda ontvangt user via it (kan voor de duidelijkheid worden hernoemd) en retourneert een geformatteerde string. Als de gebruiker niet is gevonden — geeft de Elvis-operator ?: een standaardwaarde. In het tweede voorbeeld transformeert let een string naar een getal met mogelijke null.

run — analoog aan let met toegang via this, die het resultaat van de lambda retourneert. run is handig voor berekeningen waarbij de context van het object nodig is, maar een nieuwe waarde wordt geretourneerd. Een run()-aanroep zonder object (zoals run { ... }) creëert een tijdelijk bereik voor variabelen. with — geen extensie met toegang via this, geschikt voor het groeperen van aanroepen zonder koppeling.

kotlin
// run als contextgestuurde berekening
val transformed = listOf(1, 2, 3).run {
    filter { it > 1 }.map { it * 10 }
}
println(transformed) // [20, 30]

// with voor groeperen van aanroepen
val info = with(StringBuilder()) {
    append("Name: ")
    append("Alice")
    toString()
}

In het voorbeeld retourneert run op een lijst het resultaat van filteren en mappen — de transformatie zelf, niet de lijst. with neemt StringBuilder als argument (niet via een punt) en werkt intern met this: append, append, toString. Het resultaat van with — de string info. De keuze tussen run en with is vaak subjectief, maar with heeft de voorkeur wanneer het object van een andere plaats wordt doorgegeven zonder aanroepketen.

with: context zonder extensie

with verschilt van de andere scope functions doordat het geen extensiefunctie is. Het neemt het object als eerste argument en de lambda als tweede. Binnen de lambda is het object toegankelijk via this. with is handig voor het groeperen van methodeaanroepen van het object zonder het resultaat op te slaan of wanneer tijdelijk “in de context” moet worden gegaan om meerdere eigenschappen te lezen.

kotlin
val user = User("Alice", "alice@example.com", "Admin")

val summary = with(user) {
    "User $name has role $role and email $email"
}
println(summary)

// with voor initialisatie van UI-component
with(TextView(context)) {
    text = "Hello"
    textSize = 18.0f
    setTextColor(Color.BLUE)
}

In het eerste voorbeeld vormt with de string summary door rechtstreeks via this toegang te krijgen tot de eigenschappen van user. Zonder with zou men „User ${user.name} has role ${user.role}” moeten schrijven — herhaaldelijk user herhalen. In het tweede voorbeeld groepeert with de configuratie van TextView: alle methoden en eigenschappen worden op één object aangeroepen zonder herhaling. Nadeel van with — onmogelijkheid om in een keten te gebruiken, omdat het geen extensie is en het contextobject niet retourneert.

Veelgestelde vragen

Welke scope function kiezen voor initialisatie van een object?

Gebruik apply — het retourneert het object en biedt toegang via this, waardoor eigenschappen kunnen worden ingesteld zonder herhaling van de objectnaam. also is geschikt als een expliciete parameter it nodig is voor onderscheid van de eigenschappen van het object.

Wat is het verschil tussen let en run?

let geeft context door via it (expliciete parameter), run — via this (impliciete ontvanger). let is handig voor null-controles en transformaties, run — voor berekeningen met context. Beide retourneren het resultaat van de lambda.

Wanneer with gebruiken in plaats van apply?

with is geen extensie — het neemt het object als argument. Gebruik with voor het groeperen van aanroepen wanneer een keten niet nodig is. apply — extensie die het object retourneert, handig in initialisatoren en builder-patronen.

Kan men een scope function in een andere nesten?

Ja, maar wees voorzichtig met this — geneste this veroorzaken verwarring. Gebruik let of also met expliciete namen voor geneste contexten om dubbelzinnigheid bij het verwijzen naar het externe object te voorkomen.

Welke scope function is het meest performant?

Alle scope functions zijn inline, dus ze creëren geen overhead voor anonieme klassen. Het prestatieverschil tussen hen is verwaarloosbaar. De keuze moet gebaseerd zijn op leesbaarheid en conventies, niet op snelheid.

Samenvatting

  • Scope functions — vijf inline Kotlin-functies (let, run, with, apply, also) voor het uitvoeren van code in de context van een object
  • apply retourneert het contextobject met toegang via this — ideaal voor initialisatie van eigenschappen
  • also retourneert het contextobject met toegang via it — geschikt voor loggen en bijwerkingen
  • let retourneert het resultaat van de lambda met toegang via it — basis voor null-veilige transformaties
  • run retourneert het resultaat van de lambda met toegang via this — handig voor berekeningen met context
  • with is geen extensie en retourneert het resultaat van de lambda — geschikt voor groeperen van aanroepen zonder keten
  • Combinatie van kenmerken (this/it en retourneren van object/resultaat) bepaalt de keuze van scope function voor elke taak

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