如何使用Kotlin的types安全建设者?

我见过很多教程,但仍然没有得到它的工作原理。 我明白了一个主要想法:一个函数用数据保存函数,但是看官方文档,我不知道数据存储的方式和位置,以及调用负责存储数据的函数。 其他教程似乎只显示了一小段代码,这对我没有多大帮助。 你能给我一个完整和简单的例子,像一个人,一个微不足道的类,请吗?

我也对一些细节感兴趣。 这是我写的:

data class Person( var name: String? = null, var age: Int? = null, val children: MutableList = ArrayList() ) { fun child(init: Person.() -> Unit): Person { val child = Person() children.add(child) child.init() return child } } fun person(init: Person.() -> Unit): Person { val p = Person() p.init() return p } fun main(args: Array) { 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=[]) ]) 

Kotlin DSLs

Kotlin非常适合编写自己的域特定语言 ,也称为types安全的构建器 。 Anko是使用这种DSL的例子之一。 您需要了解的最重要的语言function称为“函数接收函数” ,您已经使用它: Test.() -> Unit

函数文字与接收器 – 基础知识

Kotlin支持“function文字与接收器”的概念。 这使我们可以在函数文本的接收方中调用方法, 而不需要任何特定的限定符 。 这与扩展函数非常相似,在扩展函数中也可以访问扩展中的接收者对象的成员。

一个简单的例子也是Kotlin标准库中最重要的function之一

 public inline fun  T.apply(block: T.() -> Unit): T { block(); return this } 

正如你所看到的,这样一个带有接收者的函数文字就是这里的参数block 。 这个块被简单地执行,接收者(它是T一个实例)被返回。 在行动中,这看起来如下:

 val foo: Bar = Bar().apply { color = RED text = "Foo" } 

我们实例化一个Bar的对象,然后调用它。 Bar的实例成为“接收者”。 作为{} (lambdaexpression式)中的parameter passing的block不需要使用其他限定符来访问和修改显示的可见属性的colortext

带有接收器的函数文字 – 在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作为接收方。 在函数体中,可以看到它是如何使用的:创建一个HTML实例,并在其上调用init

效益

这样的高阶函数的调用者期待与接收者(如html() )函数文字),你可以使用任何可见的HTML函数和属性没有额外的限定符(如this ),你可以在调用中看到:

 html { // lambda with receiver begins here body() // calling a method on the receiver object } 

我已经写了一个示例DSL,并在博客文章中描述它非常详细。 也许这也有帮助。