Lambda 与 Receiver 的目的是什么?
What is a purpose of Lambda's with Receiver?
在我们有扩展函数的情况下,Lambda 在 Kotlin 中使用 Receiver 的目的是什么?
下面的两个函数做同样的事情,但第一个函数可读性更强且更短:
fun main(args: Array<String>) {
println("123".represents(123))
println(123.represents("123"))
}
fun String.represents(another: Int) = toIntOrNull() == another
val represents: Int.(String) -> Boolean = {this == it.toIntOrNull()}
带有接收器的 Lambda 基本上与扩展函数完全相同,它们只是能够存储在属性中,并传递给函数。这道题和"What's the purpose of lambdas when we have functions?"本质上是一样的。答案也大同小异 - 它允许您在代码中的任何位置快速创建匿名扩展函数。
这方面有很多很好的用例(具体参见 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
上多次调用它] 实例,存储以备后用等
相似度
扩展函数,从某种意义上说,就是一个带有接收者的函数。当您将 lambda 与接收器一起使用时,您正在利用 Kotlin 的扩展功能特性。
A lambda 是一种定义类似于 常规函数 .
行为的方法
带有接收器的 lambda 是一种定义类似于 扩展函数 .
行为的方法
要了解 lambda 与接收器的用途,请考虑以下创建 returns 一个 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
。这只是一个小例子。如果表达式较长或重复多次,会很不方便,也不好看。
目的
为了使它更简洁、漂亮和更具可读性,我们使用带有扩展函数的 receiver 的 lambda apply()
。并重构上面的代码如下:
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。
在我们有扩展函数的情况下,Lambda 在 Kotlin 中使用 Receiver 的目的是什么?
下面的两个函数做同样的事情,但第一个函数可读性更强且更短:
fun main(args: Array<String>) {
println("123".represents(123))
println(123.represents("123"))
}
fun String.represents(another: Int) = toIntOrNull() == another
val represents: Int.(String) -> Boolean = {this == it.toIntOrNull()}
带有接收器的 Lambda 基本上与扩展函数完全相同,它们只是能够存储在属性中,并传递给函数。这道题和"What's the purpose of lambdas when we have functions?"本质上是一样的。答案也大同小异 - 它允许您在代码中的任何位置快速创建匿名扩展函数。
这方面有很多很好的用例(具体参见 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
上多次调用它] 实例,存储以备后用等
相似度
扩展函数,从某种意义上说,就是一个带有接收者的函数。当您将 lambda 与接收器一起使用时,您正在利用 Kotlin 的扩展功能特性。
A lambda 是一种定义类似于 常规函数 .
行为的方法带有接收器的 lambda 是一种定义类似于 扩展函数 .
行为的方法要了解 lambda 与接收器的用途,请考虑以下创建 returns 一个 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
。这只是一个小例子。如果表达式较长或重复多次,会很不方便,也不好看。
目的
为了使它更简洁、漂亮和更具可读性,我们使用带有扩展函数的 receiver 的 lambda apply()
。并重构上面的代码如下:
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。