与安科一样,您可以编写如下回调函数:
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")
}
}不起作用。我在这里仍然缺乏一些基本概念。有人能在这里指路吗?
发布于 2017-09-08 10:52:34
Kotlin DSL
Kotlin很适合编写您自己的域特定语言,也称为型安全建筑商。正如您提到的,Anko库是使用DSL的一个示例。这里您需要理解的最重要的语言特性是“功能文字与接收者”,您已经使用了它: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的一个可见方法。
带有接收端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<String>) {
temp {
onSuccess {
toast("Hello")
}
}
}发布于 2017-09-08 12:16:46
在您的示例中,警报是返回某些类的函数,例如Alert。此外,此函数以接收方为参数函数文字。
在您的示例中,您应该使您的onSuccess成为测试类的成员方法,并且您的temp函数应该在不调用它的情况下返回测试类的实例。但是要像您所希望的那样调用to,它必须是onSuccess返回的任何类的成员函数。
我想你不太明白接收者的功能文字是如何工作的。当您玩得很开心(某样东西:A() ->单元)时,它意味着这个“东西”是A类的成员函数。
所以
你可以看看我的博客文章:如何为AsyncTask制作小型DSL
https://stackoverflow.com/questions/46113833
复制相似问题