Kotlin 之 let、with、run、apply、also 函数的使用

这篇具有很好参考价值的文章主要介绍了Kotlin 之 let、with、run、apply、also 函数的使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、内联拓展函数 let

let 扩展函数的实际上是一个作用域函数,当你需要去定义一个变量在一个特定的作用域范围内,let函数的是一个不错的选择;let函数另一个作用就是可以避免写一些判断null的操作。

1.1 let 函数的使用的一般结构

object.let {
    it.todo() //在函数体内使用it替代object对象去访问其公有的属性和方法
    ...
}

//另一种用途 判断object为null的操作
object?.let { //表示object不为null的条件下,才会去执行let函数体
    it.todo()
}

1.2 let函数底层的inline扩展函数+lambda结构

@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}

意思就是 T 类型的对象调用 let 方法,实际调用的是传入 let 方法的 lambda 表达式的 block 块,最终返回 lambda 表达式的返回值。

lambda 表达式内部通过 it 指代该对象。

1.3 let 函数常见的适用的场景

  • 场景一: 最常用的场景就是使用let函数处理需要针对一个可null的对象统一做判空处理。

  • 场景二: 然后就是需要去明确一个变量所处特定的作用域范围内可以使用

obj?.funA()
obj?.funB()
obj?.funC()

obj?.let {
    it.funA()
    it.funB()
    it.funC()
}

二、内联函数 with

2.1 with 函数使用的一般结构

with(object) {
    //todo
}

2.2 with 函数底层的inline扩展函数+lambda 结构

@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return receiver.block()
}

注意,这个 with 函数不是拓展函数,它接收两个参数,第一个参数是要是用的对象,第二个参数是一个 lambda 表达式,该方法实际调用的是第一个参数对象,进行 block 块的调用,

最终返回 lambda 表达式的返回值。

lambda 表达式内部通过 this 指代该对象。

2.3 with 函数的适用的场景

适用于调用同一个类的多个方法时,可以省去类名重复,直接调用类的方法即可,经常用于Android中RecyclerView中onBinderViewHolder中,数据model的属性映射到UI上。

obj.funA()
obj.funB()
obj.funC()

with(obj) {
    this.funA()
    funB() // this 可省略
    funC)
}

三、 内联拓展函数 run

3.1 run 函数使用的一般结构

object.run {
    // todo
}

3.2 run 函数的inline+lambda 结构

@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}

run 函数实际上可以说是let和with两个函数的结合体,run函数只接收一个lambda函数为参数,以闭包形式返回,即返回 lambda 表达式的返回值。

3.3 run 函数的适用场景

obj?.funA()
obj?.funB()
obj?.funC()

obj?.run {
    this.funA()
    funB() // this 可省略
    funC)
}

四、内联拓展函数 apply

4.1 apply 函数使用的一般结构

object.apply {
    // todo
}

4.2 apply 函数的inline+lambda结构

@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    returnthis
}

从结构上来看apply函数和run函数很像,唯一不同点就是它们各自返回的值不一样,run函数是以闭包形式返回最后一行代码的值,而apply函数的返回的是传入对象的本身。

五、内联扩展函数 also

5.1 also 函数使用的一般结构

object.also {
    // todo
}

5.2 also 函数的inline+lambda结构

public inline fun <T> T.also(block: (T) -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block(this)
    returnthis
}

also函数的结构实际上和let很像唯一的区别就是返回值的不一样,let是以闭包的形式返回,返回函数体内最后一行的值,如果最后一行为空就返回一个Unit类型的默认值。而also函数返回的则是传入对象的本身。

六、比较总结

函数名

定义inline的结构

函数体内使用的对象

返回值

是否是扩展函数

let

fun T.let(block: (T) -> R): R = block(this)

it指代当前对象

闭包形式返回

with

fun with(receiver: T, block: T.() -> R): R = receiver.block()

this指代当前对象或者省略

闭包形式返回

run

fun T.run(block: T.() -> R): R = block()

this指代当前对象或者省略

闭包形式返回

apply

fun T.apply(block: T.() -> Unit): T

this指代当前对象或者省略

返回this

also

fun T.also(block: (T) -> Unit): T

it指代当前对象

返回this

七、实用例子————Kotlin 实现单例模式

Kotlin 实现单例模式相对 java 来说很简单。比如通过 object, by lazy 操作,相信大家都会。但有时候,我们想要在单例初始化的时候顺便做一下其它初始化,极有可能会还需要传入参数。

使用 java 时,我最喜欢的实现单例模式是静态内部类的方式,但在 Android 中经常在初始化的时候需要传入 context ,然后选择了双重检查锁方式。

先看 java 代码:

public class Singleton {
    private Singleton() {
    }

    /**
     * volatile is since JDK5
     */
    private static volatile Singleton sSingleton;

    public static Singleton getInstance() {
        if (sSingleton == null) {
            synchronized (Singleton.class) {
                // 未初始化,则初始instance变量
                if (sSingleton == null) {
                    sSingleton = new Singleton();
                }
            }
        }
        return sSingleton;
    }
}

再看看我们用 kotlin 实现

class Singleton private constructor(){
    companion object {
        @Volatile
        private var instance: Singleton? = null

        fun getInstance(context: Context): Singleton {
            return instance?: synchronized(this) {
                instance?:Singleton().also {
                    instance = it
                }
            }
        }
    }
}

如果要做初始化操作,我们完全可以在 also 函数里面去处理。文章来源地址https://www.toymoban.com/news/detail-792869.html

到了这里,关于Kotlin 之 let、with、run、apply、also 函数的使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • kotlin标准函数also

    在 Kotlin 中,also 是一个标准库函数,其作用是将一个对象作为参数传递给 Lambda 表达式,并返回该对象本身 。语法如下: 使用 also 可以使代码更加简洁,常用于一系列需要对同一个对象进行多次操作的场景。例如: 上述代码首先输出字符串的长度,然后将其赋值给 length 变

    2024年02月06日
    浏览(48)
  • 【Kotlin】DSL 领域特定语言 ( apply 标准库函数分析 | 普通匿名函数 | 扩展匿名函数 | 泛型扩展匿名函数 )

    本章总结 : 读懂 apply 标准库函数 核心是其 block: T.() - Unit 参数 , 这是 泛型扩展匿名函数 ; 泛型扩展匿名函数 T.() - Unit 演变路径 : 普通匿名函数 : () - Unit , 这个函数 参数 和 返回值 都为空 ; 扩展匿名函数 : String.() - Unit , 这个函数 是 为 具体的 String 类型定义的扩展函数 ; 泛型

    2023年04月09日
    浏览(39)
  • 【第三阶段】kotlin中使用带let的安全调用

    let常常和?.配合使用,如果前面的对象为null,let不执行,能够执行到let里面 对象一定不为null 1.不为null 执行结果 2.为“ ” 执行结果 3.为null 执行结果

    2024年02月12日
    浏览(42)
  • 【错误记录】Android Studio 中 Kotlin 版本报错 ( Module was compiled with an incompatible version of Kotlin. T )

    在 Android Studio 中 , 编译应用 , 报如下错误 : 这个报错问题 , 出现了十几次 ; 详细报错信息如下 : 下面的报错信息 , 仅做参考 , 就不要点开了 ; 核心报错信息如下 : Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.6.0, expected version is 1.1.13. 大概含义就

    2024年02月05日
    浏览(52)
  • Kotlin判断null比较let布尔值Boolean

    data.count != null data.count!! true false false kotlin,null let expression_zhangphil的博客-CSDN博客 当a不为null时,执行大括号里的语句(it肯定不为null)如果a == null ,则为 null。= null,则a.b()如果 a 不是 b,则为 null。当a==null时,执行b。当a不为null时,执行大括号里的语句(it肯定不为null)如果a

    2024年02月10日
    浏览(61)
  • Android kotlin高阶函数与Java lambda表达式介绍与实战

            目前在Java JDK版本的不断升高,新的表达式已开始出现,但是在Android混淆开发中,kotlin的语言与Java的语言是紧密贴合的。所以Java lambda表达式在kotlin中以新的身份出现:高阶函数与lambda表达式特别类似。接下来我讲会先讲Java的lambda,再介绍kotlin的高阶函数。 2.1

    2024年02月15日
    浏览(50)
  • 【错误记录】Android Studio 编译报错 ( Module was compiled with an incompatible version of Kotlin. The binary )

    Android Studio 工程在编译时 , 报如下错误 : 直接把报错信息翻译一下 : 报错的模块是 e: C:/Users/octop/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.7.10/bac80c520d0a9e3f3673bc2658c6ed02ef45a76a/kotlin-stdlib-common-1.7.10.jar!/META-INF/kotlin-stdlib-common.kotlin_module 模块 , 就是 kotlin-stdlib-c

    2024年01月20日
    浏览(54)
  • Android kotlin序列化之@Parcelize详解与使用

            在Android开发过程中,序列化使用概率一直很高。在页面之间传递的对象,需要要使用序列化,常见的序列化:Parcelable、Serialization。         由于Parcelable在传递压缩比高,效率高,一直被Google官方推荐。在Java语言中,Parcelable可以通过IDE自动生成,但是在kot

    2024年02月08日
    浏览(49)
  • Android kotlin实战之协程suspend详解与使用

            Kotlin 是一门仅在标准库中提供最基本底层 API 以便各种其他库能够利用协程的语言。与许多其他具有类似功能的语言不同, async  与  await  在 Kotlin 中并不是,甚至都不是标准库的一部分。此外,Kotlin 的  挂起函数  概念为异步操作提供了比 future 与 pro

    2024年02月03日
    浏览(43)
  • Android使用Gradle kotlin dsl 优雅配置构建项目

    Gradle的出现可以说是为Android的项目构建插上了翅膀,让Android的apk打包构建更简单高效。开发者可以自己去定义打包的过程,比如在打包的过程中进行字节码插桩,多渠道打包,在老版本的Android中还可以依赖Gradle实现APP的插件化开发。但是Gradle是使用Groovy语言开发的,虽然说

    2024年02月13日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包