如何创建Kotlin DSL-DSL语法Kotlin [英] How to create Kotlin DSL - DSL syntax Kotlin

查看:738
本文介绍了如何创建Kotlin DSL-DSL语法Kotlin的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

anko 一样,您可以编写如下回调函数:

As with anko you can write callback functions like this:

alert {
    title = ""
    message = ""
    yesButton {
       toast("Yes") 
    }
    noButton { 
       toast("No")
    }
}

如何创建这样的嵌套函数?我尝试像下面这样创建它,但是似乎没有用.

How can I create a nested functions like that? I tried creating it like below but doesn't seem to be working.

class Test {
    fun f1(function: () -> Unit) {}
    fun f2(function: () -> Unit) {}
}

现在,如果我将其与扩展功能一起使用,

Now, if I use this with extension function,

fun Context.temp(function: Test.() -> Unit) {
    function.onSuccess() // doesn't work
}

从活动中调用此方法:

temp {
    onSuccess {
        toast("Hello")
    }
}

不起作用.我在这里仍然缺少一些基本概念.有人可以在这里指导吗?

Doesn't work. I am still lacking some basic concepts here. Can anyone guide here?

推荐答案

Kotlin DSL

Kotlin非常适合编写您自己的 Domain Specific Languages (也称为类型安全的构建器.如您所述,Anko库是利用DSL的示例.您需要在这里理解的最重要的语言功能称为函数文字使用Receiver" ,您已经使用了它:Test.() -> Unit

Kotlin DSLs

Kotlin is great for writing your own Domain Specific Languages, also called type-safe builders. As you mentioned, the Anko library is an example making use of DSLs. The most important language feature you need to understand here is called "Function Literals with Receiver", which you made use of already: Test.() -> Unit

Kotlin支持带有接收器的函数文字"的概念.这样,就可以在函数常量主体中的接收器上调用可见方法,而无需任何特定的限定符. 与扩展功能非常相似,在扩展功能中,还可以访问扩展内的接收者对象的成员.

Kotlin supports the concept of "function literals with receivers". This enables calling visible methods on the receiver of the function literal in its body without any specific qualifiers. This is very similar to extension functions, in which it’s also possible to access members of the receiver object inside the extension.

apply是一个简单的示例,也是Kotlin标准库中最酷的功能之一:

A simple example, also one of the coolest functions in the Kotlin standard library, isapply:

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

如您所见,带有接收器的函数文字在此处用作参数block.该block只需执行,然后返回接收者(是T的实例).实际上,它如下所示:

As you can see, such a function literal with receiver is taken as an argument block here. This block is simply executed and the receiver (which is an instance of T) is returned. In action this looks as follows:

val text: String = StringBuilder("Hello ").apply {
            append("Kotliner")
            append("! ")
            append("How are you doing?")
        }.toString()

A StringBuilder用作接收器,并在其上调用apply.在block(lambda表达式)中作为参数传递的block不需要使用其他限定符,只需多次调用append(可见的StringBuilder方法)即可.

A StringBuilder is used as the receiver and apply is invoked on it. The block, passed as an argument in {}(lambda expression), does not need to use additional qualifiers and simply calls append, a visible method of StringBuilder multiple times.

如果您查看此示例(摘自文档),将会看到它的实际效果:

If you look at this example, taken from the documentation, you see this in action:

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.

The html() function expects such a function literal with receiver with HTML as the receiver. In the function body you can see how it is used: an instance of HTML is created and the init is called on it.

这样的高阶函数的调用者期望带有接收方的函数文字(例如html()),您可以使用任何可见的HTML函数和属性而无需其他限定符(例如this例如),如您在通话中看到的那样:

The caller of such an higher-order function expecting a function literal with receiver (like html()) you can use any visible HTML function and property without additional qualifiers (like this e.g.), as you can see in the call:

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

您的示例

我创建了一个您想要拥有的简单示例:

Your Example

I created a simple example of what you wanted to have:

class Context {
    fun onSuccess(function: OnSuccessAction.() -> Unit) {
        OnSuccessAction().function();
    }

    class OnSuccessAction {
        fun toast(s: String) {
            println("I'm successful <3: $s")
        }
    }
}

fun temp(function: Context.() -> Unit) {
    Context().function()
}

fun main(args: Array<String>) {
    temp {
        onSuccess {
            toast("Hello")
        }
    }
}

这篇关于如何创建Kotlin DSL-DSL语法Kotlin的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆