Kotlin里的takeIf和takeUnless

1.介绍

我们使用kotlin的时候,会经常用到一些如let、apply、run这些作用域函数,它能让我们方便、简洁地链式调用对象的方法,除了这些,Kotlin标准库还提供了 takeIf 函数和 takeUnless 函数. 这些函数允许你在链式调用中加入对象的状态检查。

2.使用场景

我们在写if语句的时候经常会遇到这样的场景:前面调用了一个函数计算得出了一个结果,现在需要对这个结果做一个分支判断,并且我们只需要用到if的一个分支时,可以用takeIf和takeUnless代替

    fun testWithoutTakeIf() {
        val name = "maozonghong"
        val hasMao = name.indexOf("mao")
        Log.i(TAG, "testWithoutTakeIf: hasMao = $hasMao")
        if (hasYan >= 0) {
            Log.i(TAG, "testWithoutTakeIf: has mao")
        }
        Log.i(TAG, "testWithoutTakeIf: $name")
    }
    
输出:
I: testWithoutTakeIf: hasMao = 0
I: testWithoutTakeIf: has mao
I: testWithoutTakeIf: maozonghong

可以写成:

    fun testTakeIf() {
        val name = "maozonghong"
        name.indexOf("mao")
            .takeIf {
                Log.i(TAG, "testTakeIf: it = $it")
                it >= 0
            }
            ?.let {
                Log.i(TAG, "testTakeIf: has mao")
            }
        Log.i(TAG, "testTakeIf: $name")
    }
   
输出:
I: testTakeIf: it = 0
I: testTakeIf: has mao
I: testTakeIf: maozonghong

用法

1. takeif

public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
    contract {
        callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
    }
    return if (predicate(this)) this else null
}
  • 是扩展函数
  • 上下文对象的引用方式:it
  • 返回值:如果代码块predicate里面返回为true,则返回这个对象本身,否则返回空
  • 使用注意:结果要用?判空

2.takeUnless

public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? {
    contract {
        callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
    }
    return if (!predicate(this)) this else null
}
  • 是扩展函数
  • 上下文对象的引用方式:it
  • 返回值:如果代码块predicate里面返回为false,则返回这个对象本身,否则返回空
  • 使用注意:结果要用?判空

说明

从上面的用法可见它们之间的区别就只有一个是满足代码块里面的条件才返回对象本身,一个是不满足条件才返回,如例子用takeUnless写可以写成:

    fun testTakeUnless() {
        val name = "maozonghong"
        name.indexOf("mao")
            .takeUnless {
                Log.i(TAG, "testTakeUnless: it = $it")
                it < 0
            }
            ?.let {
                Log.i(TAG, "testTakeUnless: has mao")
            }
        Log.i(TAG, "testTakeUnless: $name")
    }
    
输出:
I: testTakeUnless: it = 0
I: testTakeUnless: has  mao
I: testTakeUnless: maozonghong

优点

  • 可以配合其他作用域函数返回的结果,做出单向判断,保持链式调用
  • 简化写法,逻辑清晰,减少代码量,代码更优雅。

如果需要两个分支?

name.indexOf("mao")
            .takeIf {
                Log.i(TAG, "testTakeIf: it = $it")
                it >= 0
            }
            ?.let {
                Log.i(TAG, "testTakeIf: has mao")
            }?: run{
Log.i(TAG, "testTakeIf: no mao")
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容