首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何与Kotlin的类型安全建设者一起工作?

如何与Kotlin的类型安全建设者一起工作?
EN

Stack Overflow用户
提问于 2018-01-16 16:43:48
回答 3查看 2.8K关注 0票数 4

我已经看过很多教程,但仍然没有确切地了解它是如何工作的。我理解其中的主要思想:一个用数据保存函数的函数,但看看正式文件,我不知道数据是如何存储的,数据存储在哪里,以及谁调用了负责其存储的函数。其他教程似乎只展示了一段代码片段,这对我没有多大帮助。你能给我一个简单完整的例子吗?你能给我一个简单的例子吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-01-16 17:02:45

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

代码语言:javascript
复制
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)
}

它打印出(添加了一些格式):

代码语言:javascript
复制
Person(name=Mommy, age=33, children=[
    Person(name=Gugu, age=2, children=[]), 
    Person(name=Gaga, age=3, children=[])
])
票数 3
EN

Stack Overflow用户

发布于 2018-01-16 20:07:41

Kotlin DSL

Kotlin很适合编写您自己的域特定语言,也称为型安全建筑商。Anko就是使用这种DSL的例子之一。这里您需要理解的最重要的语言特性是“功能文字与接收者”,您已经使用了它:Test.() -> Unit

带接收基的函数字面值

Kotlin支持“带有接收者的函数文字”的概念。这使我们能够在其正文中调用函数文字的接收器上的方法,而不需要任何特定的限定符。这是非常类似于扩展函数的,在扩展函数中,也可以访问扩展内的接收方对象的成员。

一个简单的例子,也是Kotlin标准库中最大的函数之一,是apply

代码语言:javascript
复制
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }

正如您所看到的,这样一个带有接收方的函数文本被作为参数block在这里。简单地执行这个块,并返回接收器(它是T的一个实例)。在行动中,如下所示:

代码语言:javascript
复制
val foo: Bar = Bar().apply {
    color = RED
    text = "Foo"
}

我们实例化Bar的一个对象并在其上调用applyBar的实例成为“接收者”。作为参数在block (lambda表达式)中传递的{}不需要使用附加限定符来访问和修改显示的可见属性colortext

带有接收端DSL的函数文本

如果您从文档中看到这个示例,您将看到以下操作:

代码语言:javascript
复制
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 ),正如您在调用中看到的那样:

代码语言:javascript
复制
html {       // lambda with receiver begins here
    body()   // calling a method on the receiver object
}

示例

我编写了一个示例DSL并在博客帖子中对其进行了描述。也许这也有帮助。

票数 3
EN

Stack Overflow用户

发布于 2022-07-25 07:03:12

只是为了添加其他语法

代码语言:javascript
复制
data class QCMBean(var qcmId : Int=-1, var question : String = "", var answers : ArrayList<AnswerBean> = ArrayList()) {

    companion object {
        fun qcm(init:QCMBean.()->Unit) = QCMBean().apply {
            init()
        }
    }
    fun answer(answer:String = "") = AnswerBean(answer).apply {
        answers.add(this)
    }
}
data class AnswerBean(var answer:String = "")


 qcm {
        qcmId = 1
        question = "How many cat ?"
        answer("1")
        answer("2")
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48286031

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档