我正在尝试为个人项目创建一个易于使用的 html 生成器。我想我会使用扩展函数来以编程方式生成 html,如下所示:
html {
head {
title("Site title")
}
body {
div {
// stuff in div
}
}
}
为此我声明了一个接口(interface):
fun interface TagBlock {
operator fun Tag.invoke()
}
其中 Tag
是指定特定标签的类,例如 html
、body
、div
等:
class Tag(val name: String)
我现在尝试创建一个接受前面提到的接口(interface)并返回标签的函数:
fun html(block: TagBlock): Tag {
val html = Tag("html")
// invoke `block` with `html`
return html
}
我不知道如何调用提供的参数block
。以下全部不起作用:
block(html) // Unresolved reference
block.invoke(html) // unresolved reference
html.block() // Unresolved reference: block
我哪里做错了?
最佳答案
您声明的 invoke()
运算符有 2 个接收器:
- 调度接收者
TagBlock
- 显式接收者
标签
您需要在调用上下文中提供调度接收器才能使其正常工作。您可以使用库函数 with()
来完成此操作:
fun html(block: TagBlock): Tag {
val html = Tag("html")
with(block) {
html.invoke()
}
return html
}
但这可能是也可能不是您正在寻找的使用体验。
Kotlin 中更惯用的方法是仅采用函数类型作为输入:
fun html(block: Tag.() -> Unit): Tag {
val html = Tag("html")
html.block()
return html
}
关于kotlin - 调用接口(interface)中声明的接收器函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67605390/