与anko一样,您可以编写如下的回调函数:
alert {
title = ""
message = ""
yesButton {
toast("Yes")
}
noButton {
toast("No")
}
}
如何创建这样的嵌套函数?我试着像下面那样创建它,但似乎没有工作。
class Test {
fun f1(function: () -> Unit) {}
fun f2(function: () -> Unit) {}
}
现在,如果我将它与扩展功能一起使用,
fun Context.temp(function: Test.() -> Unit) {
function.onSuccess() // doesn't work
}
从活动中调用此内容:
temp {
onSuccess {
toast("Hello")
}
}
不起作用。我在这里仍然缺乏一些基本概念。谁能在这里指导?
答案 0 :(得分:12)
Kotlin非常适合编写自己的特定领域语言,也称为type-safe builders。如您所述,Anko库是一个使用DSL的示例。您需要了解的最重要的语言功能称为"Function Literals with Receiver",您已经使用了它:Test.() -> Unit
Kotlin支持“带接收器的函数文字”的概念。这样可以在其主体中的函数文字的接收器上调用可见方法,而无需任何特定限定符。这非常类似于扩展函数,其中也可以访问扩展中的接收者对象的成员。
一个简单的例子,也是Kotlin标准库中最酷的函数之一,是apply
:
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
如您所见,带接收器的这种函数文字在此处被视为参数block
。简单地执行此block
并返回接收者(其为T
的实例)。在行动中,这看起来如下:
val text: String = StringBuilder("Hello ").apply {
append("Kotliner")
append("! ")
append("How are you doing?")
}.toString()
StringBuilder
用作接收器,并在其上调用apply
。 block
作为{}
(lambda表达式)中的参数传递,不需要使用其他限定符,只需多次调用append
StringBuilder
,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
}
eg),正如你在电话中看到的那样:
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")
}
}
}
我创建了一个你想要的简单例子:
<div> Item 1 <input name=item_description-0-item value=programme_title>
</div>
答案 1 :(得分:1)
在您的示例中,alert是返回某个类的函数,例如Alert。 此函数也作为参数函数文字与接收器
在你的例子中,你应该做你的 onSuccess Test类的成员方法,你的temp函数应该返回Test类的实例而不调用它。 但是要按照你的愿望调用toast,它必须是onSuccess返回的任何类的成员函数
我认为你并不清楚接收器的功能文字是如何工作的。 当你玩得开心时(东西:A。() - &gt;单位)这意味着这个“东西”是A类的成员函数。
所以
您可以查看我的博文:How to make small DSL for AsyncTask