我已经看过很多教程,但仍然没有得到它的确切运作方式。我理解主要的想法:一个函数保存带有数据的函数,但是看official documentation我无法知道数据的存储方式和位置以及谁调用负责其存储的函数。其他教程似乎只显示了一段代码,这对我没什么帮助。你能给我一个完整而简单的例子,一个琐碎的课程,比如一个人,好吗?
答案 0 :(得分:3)
我也对一些细节感兴趣。这是我写的:
data class Person(
var name: String? = null,
var age: Int? = null,
val children: MutableList<Person> = ArrayList()
) {
fun child(init: Person.() -> Unit) = Person().also {
it.init()
children.add(it)
}
}
fun person(init: Person.() -> Unit) = Person().apply { init() }
fun main(args: Array<String>) {
val p = person {
name = "Mommy"
age = 33
child {
name = "Gugu"
age = 2
}
child {
name = "Gaga"
age = 3
}
}
println(p)
}
打印出来(添加了一些格式):
Person(name=Mommy, age=33, children=[
Person(name=Gugu, age=2, children=[]),
Person(name=Gaga, age=3, children=[])
])
答案 1 :(得分:0)
Kotlin非常适合编写自己的特定领域语言,也称为type-safe builders。 Anko是使用此类DSL的示例之一。您需要了解的最重要的语言功能称为"Function Literals with Receiver",您已经使用了它:Test.() -> Unit
Kotlin支持“带接收器的函数文字”的概念。这使我们能够在其主体中调用函数文字的接收器上的方法,而无需任何特定的限定符。这非常类似于扩展函数,其中也可以访问扩展中的接收者对象的成员。
一个简单的例子,也是Kotlin标准库中最重要的函数之一,是apply
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
如您所见,带接收器的这种函数文字在此处被视为参数block
。简单地执行该块并返回接收器(它是T
的实例)。在行动中,这看起来如下:
val foo: Bar = Bar().apply {
color = RED
text = "Foo"
}
我们实例化Bar
的对象并在其上调用apply
。 Bar
的实例成为“接收者”。在block
(lambda表达式)中作为参数传递的{}
不需要使用其他限定符来访问和修改显示的可见属性color
和text
。
如果你看一下这个例子,取自文档,你会看到这一点:
class HTML {
fun body() { ... }
}
fun html(init: HTML.() -> Unit): HTML {
val html = HTML() // create the receiver object
html.init() // pass the receiver object to the lambda
return html
}
html { // lambda with receiver begins here
body() // calling a method on the receiver object
}
html()
函数需要这样一个带有HTML
接收器的函数文字作为接收者。在函数体中,您可以看到它的使用方式:创建HTML
的实例并在其上调用init
。
这样的高阶函数的调用者期望带有接收器的函数文字(如html()
),你可以使用任何可见的HTML
函数和属性而无需额外的限定符(比如this
eg),正如你在电话中看到的那样:
html { // lambda with receiver begins here
body() // calling a method on the receiver object
}
我已经编写了一个示例DSL并在blog post中详细描述了它。也许这也很有用。