如何与Kotlin的类型安全构建器一起工作?
我看过很多教程,但仍然不知道它是如何工作的。我理解了它的主要思想:一个用数据保存函数的函数,但我看不出数据是如何存储的,在哪里存储的,谁调用负责存储数据的函数。其他教程似乎只显示了一段代码,对我帮助不大。你能给我一个完整简单的例子,一个普通的类,比如一个人吗?我也对一些细节感兴趣。以下是我写的:如何与Kotlin的类型安全构建器一起工作?,kotlin,Kotlin,我看过很多教程,但仍然不知道它是如何工作的。我理解了它的主要思想:一个用数据保存函数的函数,但我看不出数据是如何存储的,在哪里存储的,谁调用负责存储数据的函数。其他教程似乎只显示了一段代码,对我帮助不大。你能给我一个完整简单的例子,一个普通的类,比如一个人吗?我也对一些细节感兴趣。以下是我写的: data class Person( var name: String? = null, var age: Int? = null, val childr
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)
}
科特林DSLs
Kotlin非常适合编写自己的领域特定语言,也称为。Anko就是使用这种DSL的例子之一。这里您需要了解的最重要的语言特性是调用,您已经使用了它:Test.(->Unit
带接收器的函数文字-基础
Kotlin支持“具有接收者的函数文本”的概念。这使我们能够调用函数体中函数文本的接收器上的方法,而无需任何特定的限定符。这与扩展函数非常类似,在扩展函数中,还可以访问扩展内部的接收方对象的成员
一个简单的例子是apply
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
我们实例化一个Bar
对象,并对其调用apply
。Bar
的实例成为“接收者”。在{}
(lambda表达式)中作为参数传递的块
,不需要使用其他限定符来访问和修改显示的可见属性颜色
和文本
DSL中带接收器的函数文本
如果您查看本文档中的示例,您会看到以下内容:
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
的一个实例,并对其调用init
利益
这种高阶函数的调用者需要一个带有receiver的函数文本(如html()
),您可以使用任何可见的html
函数和属性,而无需附加限定符(如this
),正如您在调用中看到的:
html { // lambda with receiver begins here
body() // calling a method on the receiver object
}
例子
我已经编写了一个DSL示例,并在一个示例中非常详细地描述了它。也许这也有帮助。所以,在fun child内部,当您调用child.init(),name=“Gugu”和age=2(用main编写)时,与在fun child中编写child.name=“Gugu”和child.age=2是一样的,对吗?是的,因为在init
块中,此
被分配给子
实例。那么功能人员仅用于构建目的?如果想要在构建之后获得一些值,我必须调用Person类,对吗?是的,您可以从中获得一个常规数据类。但是在以后的任何时候,你都可以再次调用p.child{…}
Awesome!谢谢
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 { // lambda with receiver begins here
body() // calling a method on the receiver object
}