前言
在这篇文章中,我们将了解 kotlin 中带有接收器的函数字面量。因此,在开始之前,让我们先了解一些基础知识。
首先,让我们检查如何编写函数。我们将看到如何使用函数和 StringBuilder API 来完成从给定字符串创建标签的任务。该功能看起来像,
fun appendTag(string: String): String {
return StringBuilder().append("<")
.append(string)
.append(">")
.toString()
}
现在,假设我们有两个字符串MindOrks和AfterAcademy,并且想要将字符串转换为标签,然后我们调用,
// Variables
val A = "MindOrks"
val B = "AfterAcademy"
// Using the function
appendTag(A)
appendTag(B)
在这里,我们必须调用 append 函数来打印输出。
现在,在 Kotlin 中为了缩短它,我们有一个叫做扩展函数的东西。让我们创建一个用于创建标签的扩展函数,
fun String.appendTag() {
StringBuilder().append("<")
.append(this)
.append(">")
.toString()
}
而且,我们使用 Kotlin 中的扩展函数,例如,
// Variables
val A = "MindOrks"
val B = "AfterAcademy"
// Using the extension function
A.appendTag()
B.appendTag()
在这里,您可以看到我们没有一次又一次地调用appendTag函数。相反,我们只是将appendTag称为带有点运算符的扩展。
通过调用函数和扩展函数,我们得到以下输出,
<MindOrks>
<AfterAcademy>
现在,我们已经使用 Extension 函数成功地将字符串转换为标签。
现在,我们必须了解 Lambda 和高阶函数。为此,我不打算在这里解释。您可以在此处了解有关 lambda 和扩展的所有信息。
现在,让我们创建一个高阶函数并传递一个 lambda 作为参数。
我们将创建一个名为buildString的函数并将StringBuilder作为参数传递。这将是,
fun buildString(action: (StringBuilder) -> Unit): String {
val builder = StringBuilder()
action(builder)
return builder.toString()
}
这里,
- buildString将函数动作作为参数
- 动作函数将 StringBuilder (builder) 作为参数返回 Unit (Java中的 void)
- 并且整个函数buildString返回字符串作为输出。
现在,要使用函数buildString,我们使用
buildString { builder ->
builder.append("<")
builder.append("MindOrks")
builder.append(">")
}
我们将 builder 作为参数,因为我们正在传递 action(builder)
在这里,我们调用buildString函数作为传递构建器作为函数的参数。
因此,为了用简单的术语更好地解释它,让我扩展功能。
buildString (fun someFunctionName(builder:StringBuilder) {
builder.append("<")
builder.append("MindOrks")
builder.append(">")
})
在这里,我们向buildString函数传递了一个具有StringBuilder类型参数的函数。然后我们调用参数生成器
按预期为我们执行附加操作。
注意:这仅用于说明目的。
现在,当我们删除函数并想使用 lambda 时,我们编写以下内容,
buildString { builder ->
builder.append("<")
builder.append("MindOrks")
builder.append(">")
}
我们只写在someFunctionName函数下写的部分。在这里,建造者是接收者
接收器在kotlin 中用于访问接收器类型的属性,无需任何额外的代码行或限定符
现在,为了让生活更简单,我们将使用 Idiomatic Kotlin。在那里,我们将删除 lambda 中构建器的显式依赖。
现在,让我们使用buildString lambda,
buildString { builder ->
builder.append("<")
builder.append("MindOrks")
builder.append(">")
}
在这方面,我们要实现的是,
buildString {
append("<")
append("MindOrks")
append(">")
}
在这里,我们可以使用this关键字访问构建器,并且在编写时我们可以忽略this。
为了解释我们如何做到这一点,让我再次扩展buildString lambda,
buildString (fun someFunctionName(builder:StringBuilder) {
builder.append("<")
builder.append("MindOrks")
builder.append(">")
})
注意:这仅用于说明目的。
现在,要访问 StringBuilder 的属性,我们将创建它的扩展函数。检查上面的代码示例以了解我们如何创建扩展函数。为此,我们将添加,
buildString (fun someFunctionName(builder:StringBuilder).extFn() {
builder.append("<")
builder.append("MindOrks")
builder.append(">")
})
注意:这仅用于说明目的。
并且由于现在我们在函数中引用了StringBuilder,正如我们从上面的扩展函数示例中所知道的那样。我们可以将buildString写 为,
buildString (fun someFunctionName(builder:StringBuilder).extFn() {
append("<")
append("MindOrks")
append(">")
})
现在,我们也可以删除extFn()为,
buildString (fun someFunctionName(builder:StringBuilder).() {
append("<")
append("MindOrks")
append(">")
})
在这里,可以看到我们去掉了extFn ()。
最后,我们可以删除虚拟解释函数someFucntionName并获得所需的输出,
buildString {
append("<")
append("MindOrks")
append(">")
}
在这里,您可以看到我们没有明确使用构建器。这里给出了lambda中StringBuilder的引用。我们也可以使用this来调用 StringBuilder 的属性。
现在,由于我们得到了一个扩展函数,我们需要将buildString函数替换为以下内容,
fun buildString(action: (StringBuilder).() -> Unit): String {
val stringBuilder = StringBuilder()
action(stringBuilder)
return stringBuilder.toString()
}
在这里,您只能看到一个区别,我们将代码从(StringBuilder) -> Unit更改为(StringBuilder) .() -> Unit。
如果你还记得上面创建扩展函数的代码,你会注意到我们基本上只是创建了一个类型为接收器的函数,() -> Unit 而没有StringBuilder明确指定名称。
因此,这就是您可以使用接收器创建 lambda 的方法。这些对于在 Kotlin 中创建 DSL 很有用。
杂项
在您的 Android 项目中,您可能在不知情的情况下将 lambda 与接收器一起使用。如果您使用过apply,那么您已经在使用它了。apply的代码看起来像,
public inline fun <T> T.apply(block: T.() -> Unit): T {
block()
return this
}
在这里,您可以看到它需要一个接收器类型为 Generic 的功能块。当我们使用它时,我们会写,
textView.apply {
text = "MindOrks"
setOnClickListener {
}
}
这里我们也使用了 lambda 中 TextView 的属性。这是可能的,因为 lambda 中的接收器。
最后
这份《高级kotlin强化实战》分享给大家,如果有需要的可以点击文末的微信卡片即可免费领取(含Android八大模块进阶笔记 | 面试题)
高级kotlin强化实战
1、Kotlin入门教程
2、Kotlin 实战避坑指南
3、项目实战《Kotlin Jetpack 实战》
- 从一个膜拜大神的 Demo 开始
- Kotlin 写 Gradle 脚本是一种什么体验?
- Kotlin 编程的三重境界
- Kotlin 高阶函数
- Kotlin 泛型
- Kotlin 扩展
- Kotlin 委托
- 协程“不为人知”的调试技巧
- 图解协程:suspend


281

被折叠的 条评论
为什么被折叠?



