Lambda与Receiver的目的是什么?

时间:2017-11-16 12:30:34

标签: lambda kotlin jetbrains-ide

Lambda与Kotlin的Receiver的目的是什么,而我们有扩展功能?

下面的两个函数做同样的事情,但是第一个函数更具可读性和简短性:

class

2 个答案:

答案 0 :(得分:24)

带接收器的Lambda基本上与扩展功能完全相同,它们只能存储在属性中,并传递给函数。这个问题基本上和#34;当我们有函数时lambda的目的是什么?"。答案也大致相同 - 它允许您在代码中的任何位置快速创建匿名扩展函数。

这有很多好的用例(特别参见DSLs),但我在这里给出一个简单的例子。

例如,让我们说你有这样的功能:

fun buildString(actions: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.actions()
    return builder.toString()
}

调用此函数将如下所示:

val str = buildString {
    append("Hello")
    append(" ")
    append("world")
}

启用此语言功能有几件有趣的事情:

  • 在传递给buildString的lambda中,您已进入新范围,因此可以使用新的方法和属性。在这种特定情况下,您可以使用StringBuilder类型的方法,而无需在任何实例上调用它们。
  • 这些函数调用的实际StringBuilder实例不是由您管理的 - 它由函数的内部实现来创建一个并在其上调用您的扩展函数。
  • 因此,除了在StringBuilder上调用传递给它的lambda之外,这个函数还可以执行更多操作 - 它可以在各种StringBuilder个实例上多次调用它,存放以备后用,等等。

答案 1 :(得分:1)

相似性

从某种意义上说,扩展功能是具有接收器的功能。当您将lambda与接收器一起使用时,您将利用Kotlin的扩展功能。

lambda 是一种定义行为的方式,类似于常规函数

带有接收器的 lambda 是一种定义行为的方式,类似于扩展功能

要了解接收器使用lambda的目的,请考虑以下示例函数,该函数创建并返回Button

fun createButton(): Button {
    val button = Button()
    button.text = "Some text"
    button.height = 40
    button.width = 60
    button.setOnClickListener(listener)
    button.background = drawable
    return button
}

从上面可以看到,您在button对象上调用了许多不同的方法,在每次调用中都重复了名称button。这只是一个小例子。如果该表达式较长或重复多次,将会很不方便,而且看起来也不漂亮。


目的

为了使其更简洁,美观和可读性更好,我们使用带有扩展功能apply()的lambda接收器。并重构上面的代码,如下所示:

fun createButton() = Button().apply {
    text = "Some text"
    height = 40
    width = 60
    setOnClickListener(listener)
    background = drawable
}

现在代码看起来更令人愉悦。 Button()是接收者对象,您可以调用方法并在其上设置属性。

当您创建实例并立即初始化某些属性时,这很有用。在Java中,这是使用Builder模式完成的。在Kotlin中,即使不支持apply()模式,也可以在任何对象上使用Builder

apply()函数在Kotlin标准库中的定义如下(简化):

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

您可以以类似的方式用接收器定义自己的lambda。