0Pricing
Kotlin Academy · Lekcja

@DslMarker: zapobieganie wyciekaniu odbiorcy

Używaj adnotacji @DslMarker do wymuszania reguł zagnieżdżania DSL podczas kompilacji.

@DslMarker: zapobieganie wyciekaniu odbiorcy to bezpłatna lekcja Kotlin Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Kotlin Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Problem wyciekania odbiorcy

W zagnieżdżonych językach DSL lambda wewnętrznego buildera może przypadkowo uzyskać dostęp do elementów zewnętrznego odbiorcy. Na przykład wewnątrz bloku td { } można wywołać tr { } z zewnętrznego zakresu tabeli — co niemal nigdy nie jest zamierzone.

Jak wygląda wyciekanie odbiorcy

Bez @DslMarker kompilator zezwala na wywoływanie funkcji z zewnętrznego zakresu z dowolnej wewnętrznej lambdy, co prowadzi do niejasnego i podatnego na błędy użycia języka DSL:

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

Wprowadzenie @DslMarker

@DslMarker to metaadnotacja stosowana do własnej klasy adnotacji. Każda klasa buildera oznaczona adnotacją DSL będzie miała swój niejawny odbiorca ukryty w zagnieżdżonych lambdach używających tej samej adnotacji DSL.

@DslMarker
annotation class HtmlDsl

@HtmlDsl
class Table

@HtmlDsl
class Tr

Jak działa ukrywanie niejawnego odbiorcy

Gdy dwie zagnieżdżone lambdy mają odbiorców oznaczonych tą samą adnotacją @DslMarker, zewnętrzny odbiorca jest ukrywany wewnątrz lambdy wewnętrznej. Bezpośredni dostęp do niego powoduje błąd kompilacji.

@DslMarker
annotation class HtmlDsl

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

Pełny przykład z @DslMarker

Należy zadeklarować adnotację, oznaczyć klasy builderów, a następnie pozwolić, aby zagnieżdżone wywołania metod z zewnętrznego zakresu były wykrywane w czasie kompilacji:

@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
}

Omijanie ograniczenia za pomocą this@

Jeśli rzeczywiście trzeba uzyskać dostęp do zewnętrznego odbiorcy z wewnętrznej lambdy, należy użyć etykietowanego odwołania this@OuterClass. Jest ono jawne i zamierzone, w przeciwieństwie do przypadkowego wyciekania odbiorcy.

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

@DslMarker z wieloma językami DSL

Różne języki DSL powinny używać różnych adnotacji @DslMarker. Dwa niezależne języki DSL z różnymi znacznikami nie wpływają na siebie nawet wtedy, gdy są zagnieżdżone.

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

Stosowanie do builderów i odbiorców

Adnotację DSL należy zastosować bezpośrednio do klasy buildera. Adnotacja propaguje się do każdego parametru lambdy, którego typem odbiorcy jest ta klasa. Dalsze oznaczanie poszczególnych funkcji nie jest potrzebne.

Obsługa w IDE

IntelliJ IDEA i Android Studio natychmiast oznaczają dostęp do zewnętrznego odbiorcy jako błąd, gdy używana jest adnotacja @DslMarker. Zapewnia to informację zwrotną w czasie rzeczywistym podczas tworzenia lub używania języka DSL.

Projektowanie z myślą o bezpieczeństwie

Dobrze zaprojektowany język DSL łączy każdą klasę buildera z adnotacją @DslMarker. To niewielki narzut związany z adnotacją, który znacznie poprawia wygodę korzystania z DSL i zapobiega całym kategoriom błędów po stronie użytkowników DSL.

Użycie w bibliotece standardowej

Własna adnotacja @DslMarker języka Kotlin jest używana w kotlinx.html, DSL routingu Ktor, skrypcie Gradle Kotlin oraz builderach buildMap/buildList. Jest podstawowym narzędziem każdego zaawansowanego zestawu narzędzi DSL.

Szybkie sprawdzenie

Czemu zapobiega @DslMarker?

Podsumowanie: @DslMarker

Najważniejsze informacje:

  • Bez @DslMarker zewnętrzni odbiorcy wyciekają do lambd wewnętrznego języka DSL
  • Należy zdefiniować klasę adnotacji opatrzoną metaadnotacją i zastosować ją do wszystkich klas builderów w języku DSL
  • Zagnieżdżone lambdy z tym samym znacznikiem nie mogą przypadkowo wywoływać elementów zewnętrznego zakresu
  • Gdy rzeczywiście potrzebny jest dostęp do zewnętrznego zakresu, należy użyć this@OuterClass

Często zadawane pytania

Czy lekcja „@DslMarker: zapobieganie wyciekaniu odbiorcy” jest bezpłatna?

Tak — pełny tekst „@DslMarker: zapobieganie wyciekaniu odbiorcy” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Kotlin Academy, przejdź na CoddyKit PRO. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „@DslMarker: zapobieganie wyciekaniu odbiorcy”?

Używaj adnotacji @DslMarker do wymuszania reguł zagnieżdżania DSL podczas kompilacji. Ćwiczysz Kotlin Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Kotlin Academy?

Nie wymagamy żadnego doświadczenia. Kotlin Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „@DslMarker: zapobieganie wyciekaniu odbiorcy”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Kotlin Academy?

Tak. Każda lekcja Kotlin Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Lambda z odbiorcą: podstawa DSL
  2. @DslMarker: zapobieganie wyciekaniu odbiorcy
  3. Budowanie bezpiecznego typowo DSL HTML/Config
  4. Testowanie i rozwijanie DSL bez łamania zgodności użytkowników
← Powrót do Kotlin Academy