如何创建Kotlin DSL – DSL语法Kotlin

和anko一样,你可以这样编写回调函数:

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

我怎样才能创建一个这样的嵌套function? 我试图创建它像下面,但似乎并没有工作。

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

现在,如果我用这个扩展function,

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

从Activity调用它:

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

不起作用。 我在这里还是缺乏一些基本概念。 有谁可以在这里指导?

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一个实例)被返回。 在行动中,这看起来如下:

 StringBuilder("Hello ").apply { append("Kotliner") append("! ") append("How are you doing?") }.toString()) 

我们使用StringBuilder作为接收器并调用它。 在{} (lambdaexpression式)中作为parameter passing的block不需要使用额外的限定符,只需多次调用StringBuilder的可见方法append即可。

带有接收器的函数文字 – 在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 } 

你的例子

我创建了一个你想要的简单例子:

 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) { temp { onSuccess { toast("Hello") } } } 

在你的示例中,alert是返回某个类的函数,例如Alert。 另外这个函数作为接收者的参数函数文字

在你的例子中,你应该使你的onSuccess成为Test类的成员方法,而你的临时函数应该返回Test类的实例而不用调用它。 但是,要按照你的意愿进行敬酒,必须是onSuccess返回的任何类的成员函数

我想你不明白接收机的function文字是如何工作的。 当你有乐趣的时候(某事:A.() – >单位)意味着这个“东西”是A类的成员函数。

所以

你可以看看我的博客文章: 如何为AsyncTask制作小型DSL