Scope-Funktionen — was sie sind, Arten und Anwendung in Kotlin

Autor: IT Sectr Veröffentlicht: 2026-06-23 Lesezeit: 8 Min.

Scope-Funktionen in Kotlin sind fünf Standardbibliotheksfunktionen (let, run, with, apply, also), die einen Codeblock im Kontext eines Objekts ausführen. Sie unterscheiden sich in der Art des Zugriffs auf das Objekt (über it oder this) und im Rückgabewert (Kontextobjekt oder Lambda-Ergebnis). Laut Kotlin-Dokumentation (2026) reduziert die richtige Wahl der Scope-Function den Boilerplate-Code um 25–40%. Scope-Funktionen helfen dabei, Objektinitialisierung, Konfiguration und Transformationen in einem deklarativen Stil zu schreiben.

Wichtige Punkte

  • Scope-Funktionen — fünf Kotlin-Funktionen (let, run, with, apply, also) zum Arbeiten im Objektkontext
  • Kontext über this — run, with, apply verwenden this und ermöglichen den direkten Aufruf von Objektmethoden
  • Kontext über it — let und also übergeben das Objekt als it-Parameter mit expliziter Benennung
  • Objektrückgabe — apply und also geben das Kontextobjekt für Aufrufketten zurück
  • Ergebnisrückgabe — let, run und with geben den letzten Ausdruck der Lambda zurück

Was sind Scope-Funktionen?

Scope-Funktionen sind ein Satz von fünf Funktionen (let, run, with, apply, also), die in die Kotlin-Standardbibliothek eingebaut sind. Jede von ihnen nimmt eine Lambda entgegen und ändert vorübergehend den Gültigkeitsbereich, sodass der Code innerhalb der Lambda im Kontext eines bestimmten Objekts ausgeführt wird. Dies vermeidet die Wiederholung des Objektnamens bei mehreren Aufrufen und gruppiert verwandte Operationen in einem Block.

Zwei Hauptmerkmale unterscheiden Scope-Funktionen: die Art des Zugriffs auf das Kontextobjekt (über this oder über it) und der Rückgabewert (das Kontextobjekt selbst oder das Lambda-Ergebnis). Zugriff über this macht das Objekt zu einem impliziten Empfänger — Methoden und Eigenschaften werden ohne Präfix aufgerufen. Zugriff über it übergibt das Objekt als expliziten Lambda-Parameter. Die Rückgabe des Objekts ermöglicht Verkettung, die Rückgabe des Ergebnisses ermöglicht die Zuweisung des transformierten Werts.

Historisch gesehen entstanden Scope-Funktionen als Ersatz für das klassische Builder-Muster und temporäre Variablen zur Initialisierung. Anstatt eine separate Builder-Klasse zu erstellen, schreibt der Entwickler apply { Eigenschaft1 = ...; Eigenschaft2 = ... }. Dies reduziert die Code-Menge und macht die Initialisierung lesbarer. Im Kotlin-Ökosystem werden Scope-Funktionen in allen Frameworks und Bibliotheken als standardmäßige Sprachidiome verwendet.

Vergleich der Scope-Funktionen: this vs it, Objektrückgabe vs Ergebnis

Die Wahl der richtigen Scope-Function wird durch zwei Fragen bestimmt: Möchten Sie this oder it für den Zugriff auf das Objekt verwenden, und möchten Sie das Objekt selbst oder das Lambda-Ergebnis zurückgeben? Die Kombination zweier binärer Merkmale ergibt vier mögliche Optionen, und with nimmt einen besonderen Platz als einzige Funktion ein, die keine Erweiterung ist.

FunktionZugriffRückgabeErweiterung?Typisches Szenario
letitLambda-ErgebnisjaTransformation, Null-Prüfung
runthisLambda-ErgebnisjaBerechnung mit Kontext
withthisLambda-ErgebnisneinGruppierung von Aufrufen
applythisKontextobjektjaEigenschaftsinitialisierung
alsoitKontextobjektjaNebenwirkungen, Protokollierung

Um ein Objekt ohne Rückgabe eines neuen Werts zu konfigurieren, verwenden Sie apply (Zugriff über this) oder also (Zugriff über it). Um einen neuen Wert basierend auf einem Objekt zu berechnen, verwenden Sie let (Zugriff über it) oder run (Zugriff über this). Um Aufrufe ohne Verkettung zu gruppieren, verwenden Sie with. Die Befolgung dieses Schemas macht den Code für andere mit Kotlin vertraute Entwickler vorhersagbar.

apply und also: Konfiguration mit Objektrückgabe

apply ist eine Scope-Function, die das Kontextobjekt zurückgibt und den Zugriff darauf über this ermöglicht. Dies ist das ideale Werkzeug zum Initialisieren von Objekteigenschaften nach der Erstellung. Innerhalb des apply-Blocks können Eigenschaften ohne Wiederholung des Objektnamens festgelegt werden. Die Methode gibt das Objekt selbst zurück, sodass apply in Ketten eingebettet oder in Initialisierern verwendet werden kann.

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
}

Im Listing konfiguriert apply ServerConfig, indem es direkt über this auf Eigenschaften zugreift (this wird weggelassen). Ohne apply müsste man config.host = ..., config.port = ... schreiben — drei sich wiederholende Verweise auf dieselbe Variable. Die Rückgabe des Objekts ermöglicht es, das Konfigurationsergebnis in val config zu speichern. also übergibt im Gegensatz zu apply das Objekt über it und eignet sich für Nebenwirkungen.

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

Im Beispiel wird also zur Protokollierung verwendet — während es das ursprüngliche Objekt zurückgibt, führt es eine Nebenwirkung (Ausgabe einer Nachricht) aus, ohne das Objekt zu verändern. Dies ist eine Kette: validate(user) gibt User zurück, also protokolliert das Ergebnis und gibt den Benutzer weiter. also ist auch nützlich zum Hinzufügen von Elementen zu Sammlungen oder zum Debuggen in der Mitte einer Transformationskette.

let und run: Transformationen und Berechnungen

let ist eine Scope-Function, die das Lambda-Ergebnis zurückgibt und den Kontext über it übergibt. Dies ist die primäre Funktion für nullsichere Transformationen: Wenn das Objekt nullable ist, führt die Kombination ?.let { } den Block nur für Nicht-Null-Werte aus. let wird auch verwendet, um den Gültigkeitsbereich temporärer Variablen zu begrenzen und für map-ähnliche Transformationen von einem Typ in einen anderen.

kotlin
fun findUser(id: Int): User?

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

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

Im ersten Beispiel wird let über ?. aufgerufen — der Block wird nur ausgeführt, wenn findUser nicht null zurückgegeben hat. Die Lambda nimmt user über it entgegen (kann zur Verdeutlichung umbenannt werden) und gibt eine formatierte Zeichenkette zurück. Wenn der Benutzer nicht gefunden wird, liefert der Elvis-Operator ?: einen Standardwert. Im zweiten Beispiel konvertiert let eine Zeichenkette mit potenziellem null in eine Zahl.

run ist ein Analogon zu let mit Zugriff über this, das das Lambda-Ergebnis zurückgibt. run ist praktisch für Berechnungen, die einen Objektkontext erfordern, aber einen neuen Wert zurückgeben. Der Aufruf von run() ohne Objekt (als run { ... }) erzeugt einen temporären Gültigkeitsbereich für Variablen. with ist eine Nicht-Erweiterung mit Zugriff über this, die sich zum Gruppieren von Aufrufen ohne Verkettung eignet.

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

// with zum Gruppieren von Aufrufen
val info = with(StringBuilder()) {
    append("Name: ")
    append("Alice")
    toString()
}

Im Beispiel gibt run auf einer Liste das Ergebnis der Filterung und Mapping zurück — die Transformation selbst, nicht die Liste. with nimmt StringBuilder als Argument entgegen (nicht über Punkt) und arbeitet intern mit this: append, append, toString. Das Ergebnis von with ist die Zeichenkette info. Die Wahl zwischen run und with ist oft subjektiv, aber with ist vorzuziehen, wenn das Objekt ohne Verkettung von einer anderen Stelle übergeben wird.

with: Kontext ohne Erweiterung

with unterscheidet sich von anderen Scope-Funktionen dadurch, dass es keine Erweiterungsfunktion ist. Es nimmt das Objekt als erstes Argument und die Lambda als zweites Argument entgegen. Innerhalb der Lambda ist das Objekt über this zugänglich. with ist praktisch zum Gruppieren von Objektmethodenaufrufen ohne Speichern des Ergebnisses oder wenn Sie vorübergehend in einen Kontext „eintreten“ möchten, um mehrere Eigenschaften zu lesen.

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

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

// with zur UI-Komponenteninitialisierung
with(TextView(context)) {
    text = "Hello"
    textSize = 18.0f
    setTextColor(Color.BLUE)
}

Im ersten Beispiel bildet with die Zusammenfassungszeichenkette, indem es direkt über this auf user-Eigenschaften zugreift. Ohne with müsste man „User ${user.name} has role ${user.role}“ schreiben — wiederholtes user. Im zweiten Beispiel gruppiert with die TextView-Konfiguration: Alle Methoden und Eigenschaften werden ohne Wiederholung auf einem Objekt aufgerufen. Nachteil von with — Unmöglichkeit der Verwendung in einer Kette, da es keine Erweiterung ist und kein Kontextobjekt zurückgibt.

Häufig gestellte Fragen

Welche Scope-Function sollte ich zur Objektinitialisierung wählen?

Verwenden Sie apply — es gibt das Objekt zurück und ermöglicht den Zugriff über this, sodass Sie Eigenschaften ohne Wiederholung des Objektnamens festlegen können. also ist geeignet, wenn ein expliziter it-Parameter zur Unterscheidung von Objekteigenschaften benötigt wird.

Wie unterscheidet sich let von run?

let übergibt den Kontext über it (expliziter Parameter), run über this (impliziter Empfänger). let ist praktisch für Null-Prüfungen und Transformationen, run für Berechnungen mit Kontext. Beide geben das Lambda-Ergebnis zurück.

Wann sollte man with anstelle von apply verwenden?

with ist keine Erweiterung — es nimmt das Objekt als Argument entgegen. Verwenden Sie with zum Gruppieren von Aufrufen, wenn keine Verkettung benötigt wird. apply ist eine Erweiterung, die das Objekt zurückgibt, praktisch in Initialisierern und Builder-Mustern.

Kann eine Scope-Function in eine andere verschachtelt werden?

Ja, aber seien Sie vorsichtig mit this — verschachteltes this erzeugt Verwirrung. Verwenden Sie let oder also mit expliziten Namen für verschachtelte Kontexte, um Mehrdeutigkeiten beim Verweis auf das äußere Objekt zu vermeiden.

Welche Scope-Function ist am leistungsfähigsten?

Alle Scope-Funktionen sind inline, daher erzeugen sie keinen Overhead durch anonyme Klassen. Der Leistungsunterschied zwischen ihnen ist vernachlässigbar. Die Wahl sollte auf Lesbarkeit und Konventionen basieren, nicht auf Geschwindigkeit.

Zusammenfassung

  • Scope-Funktionen — fünf Kotlin-Inline-Funktionen (let, run, with, apply, also) zur Ausführung von Code im Objektkontext
  • apply gibt das Kontextobjekt mit Zugriff über this zurück — ideal zur Eigenschaftsinitialisierung
  • also gibt das Kontextobjekt mit Zugriff über it zurück — geeignet für Protokollierung und Nebenwirkungen
  • let gibt das Lambda-Ergebnis mit Zugriff über it zurück — Grundlage für nullsichere Transformationen
  • run gibt das Lambda-Ergebnis mit Zugriff über this zurück — praktisch für Berechnungen mit Kontext
  • with ist keine Erweiterung und gibt das Lambda-Ergebnis zurück — geeignet zum Gruppieren von Aufrufen ohne Verkettung
  • Kombination von Merkmalen (this/it und Objekt-/Ergebnisrückgabe) bestimmt die Wahl der Scope-Function für jede Aufgabe

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.

Projekt besprechen

Lesen Sie auch