用于DSL的Kotlin接收器功能需要解释

用于DSL的Kotlin接收器功能需要解释,kotlin,dsl,Kotlin,Dsl,我试图理解以下代码() 我真正不能理解的是这条线 html.init() // pass the receiver object to the lambda 这里发生了什么 有人能用简单的话解释一下这里发生了什么吗?这里是一步一步的解释: 一,。创建函数,接收器类型lambda funHTML(init:html.)->Unit:html{ 这里,函数html接受类型为html.(->)Unit的参数init,也就是说,它表示它是html的接收者,只能在真实html对象的帮助下调用。:htm

我试图理解以下代码()

我真正不能理解的是这条线

html.init() // pass the receiver object to the lambda
这里发生了什么


有人能用简单的话解释一下这里发生了什么吗?

这里是一步一步的解释:

一,。创建函数,接收器类型lambda

funHTML(init:html.)->Unit:html{
这里,函数html接受类型为
html.(->)Unit
的参数
init
,也就是说,它表示它是html的接收者,只能在真实html对象的帮助下调用。
:html
表示函数显然返回html对象

2.在html中调用init

html.init()
在这里,init()函数被真正的HTML对象作为HTML的接收者调用


好了,别再正式了,以下是接受者的含义:

所以,如果您还记得扩展函数定义为
fun A.myFun(…):ReturnType{}
,那么在这种情况下,您会得到一个变量
this
,它充当调用它的类型A的实例

类似地,receiver lambda为您提供了一个
this
变量

在特定示例中:

A类{
fun this可以称为dbyainstance(){
println(“我接到电话”)
}
}
主要内容(){
val接收器:A.()->单元={//this:A
thiscalledbyainstance()//打印:我已被调用
//或者用传统的方式。这个可以称为dbyainstance()
}
val a:a=a()
a、 接收者()
}
在这里,您可以从
A
的实例调用方法(函数),即使它是lambda,因为它是一个接收器

PS:对于简单语言,您可以将html.init()视为init(html),但html不是一个参数,而是在lambda中作为
this
vaiable


这就是为什么您能够对该lambda调用
body()
,因为您隐式地调用
This.body()
This
来自
html.init()
的html对象。

这里是逐步解释:

1.创建函数,接收器类型lambda

funHTML(init:html.)->Unit:html{
这里,函数html接受类型为
html.(->)Unit
的参数
init
,也就是说,它表示它是html的接收者,只能在真实html对象的帮助下调用。
:html
表示函数显然返回html对象

2.在html中调用init

html.init()
在这里,init()函数被真正的HTML对象作为HTML的接收者调用


好了,别再正式了,以下是接受者的含义:

所以,如果您还记得扩展函数定义为
fun A.myFun(…):ReturnType{}
,那么在这种情况下,您会得到一个变量
this
,它充当调用它的类型A的实例

类似地,receiver lambda为您提供了一个
this
变量

在特定示例中:

A类{
fun this可以称为dbyainstance(){
println(“我接到电话”)
}
}
主要内容(){
val接收器:A.()->单元={//this:A
thiscalledbyainstance()//打印:我已被调用
//或者用传统的方式。这个可以称为dbyainstance()
}
val a:a=a()
a、 接收者()
}
在这里,您可以从
A
的实例调用方法(函数),即使它是lambda,因为它是一个接收器

PS:对于简单语言,您可以将html.init()视为init(html),但html不是一个参数,而是在lambda中作为
this
vaiable


这就是为什么您能够在该lambda上调用
body()
,因为隐式调用
This.body()
This
来自
html.init()
的html对象。

首先,让我们让这个示例更简单一点,看看问题是什么

我们可以像这样构建
html
函数:

fun html(init: (HTML) -> Unit): HTML {
    val html = HTML()
    init(html)
    return html
}
这将更容易理解(一开始),因为我们只是将一个常用的单参数lambda传递给
html
函数

但现在,呼叫站点不像建设者:

html { it: HTML -> // just for clarity     
    it.body() // not very nice
}
如果我们可以在
html
内部调用
body()
而不调用
it
,那不是很好吗?那是可能的!我们只需要一个带接收器的lambda

fun html(init: HTML.() -> Unit): HTML { // <-- only this changed
    val html = HTML()
    init(html)
    return html
}
由于
这个
可以省略,我们来到这里:

html {      
   body()
}

因此,最后,带有接收器的lambda使代码更加简洁,并允许我们使用一个好的构建器语法。

首先,让我们让这个示例变得简单一点,看看问题出在哪里

我们可以像这样构建
html
函数:

fun html(init: (HTML) -> Unit): HTML {
    val html = HTML()
    init(html)
    return html
}
这将更容易理解(一开始),因为我们只是将一个常用的单参数lambda传递给
html
函数

但现在,呼叫站点不像建设者:

html { it: HTML -> // just for clarity     
    it.body() // not very nice
}
如果我们可以在
html
内部调用
body()
而不调用
it
,那不是很好吗?那是可能的!我们只需要一个带接收器的lambda

fun html(init: HTML.() -> Unit): HTML { // <-- only this changed
    val html = HTML()
    init(html)
    return html
}
由于
这个
可以省略,我们来到这里:

html {      
   body()
}
因此,最终,带有接收器的lambda使代码更加简洁,并允许我们使用一个好的生成器语法。

这有帮助吗?这有帮助吗?