Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin 调用接口中声明的接收器函数_Kotlin_Extension Methods - Fatal编程技术网

Kotlin 调用接口中声明的接收器函数

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生成器。我想我应该使用扩展函数,以编程方式生成html,如下所示:

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
标记中有效。我希望这能把事情弄清楚一点:)