Kotlin Academy · Lektion

@DslMarker: Receiver-Leaks verhindern

Verwenden Sie @DslMarker-Annotationen, um Verschachtelungsregeln von DSLs zur Compile-Zeit durchzusetzen.

Lektion 2 von 413 Schritte

@DslMarker: Receiver-Leaks verhindern ist eine kostenlose Kotlin Academy-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Kotlin Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.

Das Problem von Receiver-Leaks

In verschachtelten DSLs kann ein inneres Builder-Lambda versehentlich auf Member eines äußeren Receivers zugreifen. Beispielsweise könnten Sie innerhalb eines td { }-Blocks tr { } aus dem äußeren Tabellenbereich aufrufen – was fast nie beabsichtigt ist.

So sehen Receiver-Leaks aus

Ohne @DslMarker erlaubt der Compiler, Funktionen des äußeren Gültigkeitsbereichs aus jedem inneren Lambda aufzurufen, was zu einer verwirrenden und fehleranfälligen Verwendung der DSL führt:

// Without @DslMarker — this compiles but is wrong:
html {
    body {
        table {
            tr {                // outer scope leaks in
                tr {  }         // calling tr inside tr — nonsensical
            }
        }
    }
}

@DslMarker einführen

@DslMarker ist eine Metaannotation, die Sie auf Ihre eigene Annotationsklasse anwenden. Jede mit Ihrer DSL-Annotation annotierte Builder-Klasse hat ihren impliziten Receiver in verschachtelten Lambdas ausgeblendet, die dieselbe DSL-Annotation verwenden.

@DslMarker
annotation class HtmlDsl

@HtmlDsl
class Table

@HtmlDsl
class Tr

So funktioniert das Ausblenden impliziter Receiver

Wenn zwei verschachtelte Lambdas jeweils einen mit derselben @DslMarker-Annotation markierten Receiver haben, wird der äußere Receiver innerhalb des inneren Lambdas ausgeblendet. Ein direkter Zugriff darauf führt zu einem Kompilierungsfehler.

@DslMarker
annotation class HtmlDsl

@HtmlDsl class Html
@HtmlDsl class Body
@HtmlDsl class Div

Vollständiges Beispiel mit @DslMarker

Deklarieren Sie die Annotation, markieren Sie die Builder-Klassen, und verschachtelte Aufrufe von Methoden des äußeren Gültigkeitsbereichs werden zur Kompilierzeit erkannt:

@DslMarker
annotation class MyCfgDsl

@MyCfgDsl
class ServerBuilder {
    var port: Int = 8080
    fun database(block: DbBuilder.() -> Unit) { /*...*/ }
}

@MyCfgDsl
class DbBuilder {
    var url: String = ""
    // Cannot call ServerBuilder.port here — compiler error
}

Die Einschränkung mit this@ umgehen

Wenn Sie wirklich auf einen äußeren Receiver aus einem inneren Lambda zugreifen müssen, verwenden Sie eine gelabelte this@OuterClass-Referenz. Das ist explizit und beabsichtigt, im Gegensatz zum versehentlichen Durchsickern.

fun ServerBuilder.database(block: DbBuilder.() -> Unit) {
    val db = DbBuilder()
    db.block()
    val serverPort = this@ServerBuilder.port  // explicit outer access
}

@DslMarker bei mehreren DSLs

Verschiedene DSLs sollten unterschiedliche @DslMarker-Annotationen verwenden. Zwei nicht verwandte DSLs mit verschiedenen Markern beeinflussen sich nicht, selbst wenn sie verschachtelt sind.

@DslMarker annotation class HtmlDsl
@DslMarker annotation class GradleDsl
// HtmlDsl and GradleDsl receivers do not hide each other

Auf Builder und Receiver anwenden

Wenden Sie Ihre DSL-Annotation auf die Builder-Klasse selbst an. Die Annotation wird auf jeden Lambda-Parameter übertragen, dessen Receiver-Typ diese Klasse ist. Eine weitere Annotation einzelner Funktionen ist nicht nötig.

IDE-Unterstützung

IntelliJ IDEA und Android Studio markieren den Zugriff auf den äußeren Receiver sofort als Fehler, wenn @DslMarker verwendet wird. Dies gibt beim Erstellen oder Verwenden Ihrer DSL Echtzeitfeedback.

Für Sicherheit entwerfen

Ein gutes DSL-Design kombiniert jede Builder-Klasse mit @DslMarker. Der geringe Aufwand einer Annotation verbessert die Ergonomie der DSL erheblich und verhindert ganze Fehlerkategorien für DSL-Nutzende.

Verwendung in der Standardbibliothek

Kotlin verwendet sein eigenes @DslMarker in kotlinx.html, der Ktor-Routing-DSL, Gradle-Kotlin-Skripten und den buildMap/buildList-Buildern. Es ist ein grundlegendes Werkzeug in jedem ernst zu nehmenden DSL-Toolkit.

Kurzer Test

Was verhindert @DslMarker?

Zusammenfassung: @DslMarker

Wichtigste Erkenntnisse:

  • Ohne @DslMarker sickern äußere Receiver in innere DSL-Lambdas durch
  • Definieren Sie eine mit einer Metaannotation versehene Annotationsklasse und wenden Sie sie auf alle Builder-Klassen Ihrer DSL an
  • Verschachtelte Lambdas mit demselben Marker können nicht versehentlich Member des äußeren Gültigkeitsbereichs aufrufen
  • Verwenden Sie this@OuterClass, wenn Sie tatsächlich auf den äußeren Gültigkeitsbereich zugreifen müssen
Kostenlos starten

Lerne Kotlin mit einem KI-Tutor — kostenlos

Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.

Kurse
51
Lektionen
203

Häufig gestellte Fragen

Ist die Lektion „@DslMarker: Receiver-Leaks verhindern“ kostenlos?

Ja — der vollständige Text von „@DslMarker: Receiver-Leaks verhindern“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Kotlin Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „@DslMarker: Receiver-Leaks verhindern“?

Verwenden Sie @DslMarker-Annotationen, um Verschachtelungsregeln von DSLs zur Compile-Zeit durchzusetzen. Du übst Kotlin Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Kotlin Academy zu starten?

Keine Vorkenntnisse erforderlich. Kotlin Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.

Wie lange dauert die Lektion „@DslMarker: Receiver-Leaks verhindern“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Kotlin Academy-Lektion Code schreiben und ausführen?

Ja. Jede Kotlin Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Lambda mit Receiver: Grundlage für DSLs
  2. @DslMarker: Receiver-Leaks verhindern
  3. Eine typsichere HTML-/Config-DSL erstellen
  4. DSLs testen und weiterentwickeln, ohne Nutzer zu beeinträchtigen
← Zurück zu Kotlin Academy