@DslMarker: impedindo o vazamento de receptores
Use anotações @DslMarker para impor regras de aninhamento de DSL em tempo de compilação.
@DslMarker: impedindo o vazamento de receptores é uma aula grátis de Kotlin Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Kotlin Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Kotlin Academy inclui 4 aulas no total.
O problema do vazamento de receptores
Em DSLs aninhadas, uma lambda construtora interna pode acessar acidentalmente membros de um receptor externo. Por exemplo, dentro de um bloco td { }, você poderia chamar tr { } do escopo da tabela externa — o que quase nunca é intencional.
Como é o vazamento
Sem @DslMarker, o compilador permite chamar funções do escopo externo a partir de qualquer lambda interna, o que leva a um uso confuso e sujeito a erros da DSL:
// Without @DslMarker — this compiles but is wrong:
html {
body {
table {
tr { // outer scope leaks in
tr { } // calling tr inside tr — nonsensical
}
}
}
}Introduzindo @DslMarker
@DslMarker é uma meta-anotação que você aplica à sua própria classe de anotação. Qualquer classe construtora anotada com a anotação da sua DSL terá seu receptor implícito oculto em lambdas aninhadas que usam a mesma anotação da DSL.
@DslMarker
annotation class HtmlDsl
@HtmlDsl
class Table
@HtmlDsl
class TrComo funciona a ocultação do receptor implícito
Quando duas lambdas aninhadas têm receptores marcados com a mesma anotação @DslMarker, o receptor externo fica oculto dentro da lambda interna. Acessá-lo diretamente causa um erro de compilação.
@DslMarker
annotation class HtmlDsl
@HtmlDsl class Html
@HtmlDsl class Body
@HtmlDsl class DivExemplo completo com @DslMarker
Declare a anotação, marque as classes construtoras e, em seguida, as chamadas aninhadas a métodos do escopo externo serão detectadas em tempo de compilação:
@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
}Escapando da restrição com this@
Se você realmente precisar acessar um receptor externo a partir de uma lambda interna, use uma referência rotulada this@OuterClass. Isso é explícito e intencional, ao contrário do vazamento acidental.
fun ServerBuilder.database(block: DbBuilder.() -> Unit) {
val db = DbBuilder()
db.block()
val serverPort = this@ServerBuilder.port // explicit outer access
}@DslMarker com várias DSLs
DSLs diferentes devem usar anotações @DslMarker diferentes. Duas DSLs não relacionadas, com marcadores diferentes, não interferem uma na outra mesmo quando estão aninhadas.
@DslMarker annotation class HtmlDsl
@DslMarker annotation class GradleDsl
// HtmlDsl and GradleDsl receivers do not hide each otherAplicando a construtoras e receptores
Aplique a anotação da sua DSL à própria classe construtora. A anotação se propaga para qualquer parâmetro de lambda cujo tipo de receptor seja essa classe. Não é necessária nenhuma anotação adicional em funções individuais.
Suporte da IDE
IntelliJ IDEA e Android Studio destacam imediatamente como erro o acesso ao receptor externo quando @DslMarker é usado. Isso fornece feedback em tempo real ao criar ou utilizar sua DSL.
Projetando para a segurança
Um bom projeto de DSL associa cada classe construtora a @DslMarker. É um pequeno custo de anotação que melhora significativamente a ergonomia da DSL e evita categorias inteiras de erros para quem a utiliza.
Uso na biblioteca padrão
O próprio @DslMarker do Kotlin é usado em kotlinx.html, na DSL de roteamento do Ktor, no script Kotlin do Gradle e nas construtoras buildMap/buildList. Ele é uma ferramenta fundamental em qualquer conjunto sério de ferramentas para DSLs.
Verificação rápida
O que @DslMarker impede?
Recapitulação: @DslMarker
Principais conclusões:
- Sem
@DslMarker, receptores externos vazam para lambdas internas da DSL - Defina uma classe de anotação com meta-anotação e aplique-a a todas as classes construtoras da sua DSL
- Lambdas aninhadas com o mesmo marcador não podem chamar acidentalmente membros do escopo externo
- Use
this@OuterClassquando realmente precisar acessar o escopo externo
Aprenda Kotlin com um tutor de IA — grátis
Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.
- Cursos
- 51
- Aulas
- 203
Perguntas Frequentes
A aula “@DslMarker: impedindo o vazamento de receptores” é grátis?
Sim — o texto completo de “@DslMarker: impedindo o vazamento de receptores” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Kotlin Academy, atualize para CoddyKit PRO. O curso de Kotlin Academy inclui 4 aulas no total.
O que vou aprender em “@DslMarker: impedindo o vazamento de receptores”?
Use anotações @DslMarker para impor regras de aninhamento de DSL em tempo de compilação. Você pratica Kotlin Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Kotlin Academy?
Nenhuma experiência prévia é necessária. Kotlin Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “@DslMarker: impedindo o vazamento de receptores”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Kotlin Academy?
Sim. Cada aula de Kotlin Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Lambda com receptor: a base da DSL
- @DslMarker: impedindo o vazamento de receptores
- Criando uma DSL de HTML/configuração segura quanto a tipos
- Testando e evoluindo DSLs sem interromper os usuários