美文网首页
Kotlin takeIf 和 takeUnless

Kotlin takeIf 和 takeUnless

作者: wuchao226 | 来源:发表于2021-09-26 17:38 被阅读0次

    除了作用域函数外,标准库还包含函数 takeIftakeUnless
    看看 takeIf 和 takeUnless 的实现:

    // takeIf
    public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
        contract {
            callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
        }
        return if (predicate(this)) this else null
    }
    
    
    // takeUnless
    public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? {
        contract {
            callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
        }
        return if (!predicate(this)) this else null
    }
    

    takeIf : 接收一个判断条件表达式,如果判断表达式为 true 则返回对象本身,false返回 null。
    takeUnless: 与 takeIf 相反, 如果判断表达式为 true 则返回 null,false 返回对象本身。

    该对象可以作为 lambda 参数 (it) 使用,过滤条件位于函数的 {} 中

    fun main() {
        val number = Random.nextInt(100)
    
        val evenOrNull = number.takeIf { it % 2 == 0 }
        val oddOrNull = number.takeUnless { it % 2 == 0 }
        println("偶数: $evenOrNull, 奇数: $oddOrNull")
    }
    
    控制台输出:
    偶数: 80, 奇数: null
    

    当在 takeIftakeUnless 之后链式调用其他函数,不要忘记执行空检查或安全调用(?.),因为他们的返回值是可为空的。

    fun main() {
        val str = "Hello"
        val caps = str.takeIf { it.isNotEmpty() }?.toUpperCase()
        //val caps = str.takeIf { it.isNotEmpty() }.toUpperCase() // 编译错误
        println(caps)
    }
    
    控制台输出:
    HELLO
    

    takeIftakeUnless 与作用域函数一起特别有用。 一个很好的例子是用 let 链接它们,以便在与给定谓词匹配的对象上运行代码块。 为此,请在对象上调用 takeIf,然后通过安全调用(?.)调用 let。对于与谓词不匹配的对象,takeIf 返回 null,并且不调用 let

    fun main() {
        fun displaySubstringPosition(input: String, sub: String) {
            input.indexOf(sub).takeIf { it > 0 }?.let {
                println("The substring $sub is found in $input.")
                println("Its start position is $it.")
            }
        }
    
        displaySubstringPosition("010000011", "11")
        displaySubstringPosition("010000011", "12")
    }
    
    控制台输出:
    The substring 11 is found in 010000011.
    Its start position is 7.
    

    没有标准库函数时,相同的函数看起来是这样的:

    fun main() {
        fun displaySubstringPosition(input: String, sub: String) {
            val index = input.indexOf(sub)
            if (index >= 0) {
                println("The substring $sub is found in $input.")
                println("Its start position is $index.")
            }
        }
    
        displaySubstringPosition("010000011", "11")
        displaySubstringPosition("010000011", "12")
    }
    

    使用场景

    有这么一种场景可以使用,如请求后台返回了一个 UserCallback 对象,需要在界面显示这个 UserCallback 包含的一个 address 字符串,如果返回的 address 如果是 null 或空字符串则显示“未设置”

    以前这种场景一般都是这样实现的:

    val addr = UserCallback.address
    textView.text = if (addr.isNullOrBlank()) "未设置" else addr
    

    但使用 takeIftakeUnless 可以这样实现更为直接:

    textView.text = UserCallback.address.takeUnless { it.isNullOrBlank() }?:"未设置"
     
    // 或者使用takeIf的写法
    // textView.text = UserCallback.address.takeIf { !it.isNullOrBlank() }?:"未设置"
    

    相关文章

      网友评论

          本文标题:Kotlin takeIf 和 takeUnless

          本文链接:https://www.haomeiwen.com/subject/oogqnltx.html