【Android】Kotlin 中带有接收器的函数字面量

9 篇文章 0 订阅

前言

在这篇文章中,我们将了解 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>