Kotlin 调用接口中声明的接收器函数
我正在尝试为个人项目创建一个易于使用的html生成器。我想我应该使用扩展函数,以编程方式生成html,如下所示:Kotlin 调用接口中声明的接收器函数,kotlin,extension-methods,Kotlin,Extension Methods,我正在尝试为个人项目创建一个易于使用的html生成器。我想我应该使用扩展函数,以编程方式生成html,如下所示: html{ 头{ 标题(“网站标题”) } 身体{ div{ //在div中填充 } } } 为此,我声明了一个接口: fun接口标记块{ 操作符fun Tag.invoke() } 其中,Tag将是指定特定标记的类,如html、body、div等: class标记(val名称:String) 我现在尝试创建一个函数,该函数接受前面提到的接口并返回一个标记: funHTML(b
html{
头{
标题(“网站标题”)
}
身体{
div{
//在div中填充
}
}
}
为此,我声明了一个接口:
fun接口标记块{
操作符fun Tag.invoke()
}
其中,Tag
将是指定特定标记的类,如html
、body
、div
等:
class标记(val名称:String)
我现在尝试创建一个函数,该函数接受前面提到的接口并返回一个标记:
funHTML(block:TagBlock):标记{
val html=Tag(“html”)
//用html调用block`
返回html
}
我一直在思考如何调用提供的参数块。以下所有操作都不起作用:
block(html)//未解析的引用
block.invoke(html)//未解析的引用
html.block()//未解析的引用:block
我哪里做错了?您声明的invoke()
运算符有两个接收器:
- 调度接收器
TagBlock
- 显式接收器
标签
您需要在调用的上下文中提供dispatch receiver,以使其正常工作。您可以使用库函数with()
:
funHTML(block:TagBlock):标记{
val html=Tag(“html”)
带(块){
html.invoke()
}
返回html
}
不过,这可能是您想要的使用体验,也可能不是
Kotlin中更惯用的方法是只将函数类型作为输入:
funHTML(块:标记。->Unit):标记{
val html=Tag(“html”)
html.block()
返回html
}
非常感谢!我首先采用惯用的方法,但后来我不得不引入标记
子类,所以我尝试了类型别名
,但遗憾的是它不支持类型约束,所以我使用自定义接口
,以减少整个项目中的冗余。但是当我读到这篇文章时,也许我会回到“更简单”的版本,只使用一个函数类型。(我知道很多但是)@Lino与Tag
子类一起,使用函数类型的方法仍然有效,因为函数可以将Tag的子类作为接收器(如果您需要更多类型约束)。或者,如果这还不够,您甚至可以想象使用泛型类型作为接收器。我可能不完全了解你想做什么:)我现在采用惯用的方法,需要多写一点,但它满足了我的需要。子类的情况是为这些函数的用户引入更多约束。也就是说,html
标记在我的情况下只允许head
和body
标记,而body
不应该出现在另一个body
-标记中,因此在这些通用约束条件下,我只能允许我选择的特定标记。另一个例子是title
标记,它仅在head
标记中有效。我希望这能把事情弄清楚一点:)