介绍

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

官方文档在此

使用场景

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

如:

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

可以写成:

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

用法

takeIf

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

takeUnless

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

说明

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

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

优点

  • 可以配合其他作用域函数返回的结果,做出单向判断,保持链式调用

  • 简化写法,逻辑清晰,减少代码量,代码更优雅(可以装逼)。

缺点

  • 太简洁也是罪,如果返回值和takeXx写在一起时,debug无法进去看到it的值(所以建议比较重要的值可以分行写或者打印出来)

  • 提升代码阅读者的理解难度(毕竟if谁都懂,takeXx要学)

如果需要两个分支?

此时也可以用takeIf和takeUnless,可以加上elvis 操作符来做第二个分支的操作:

        name.indexOf("yan").takeIf {Log.i(TAG, "testTakeIf: it = $it")it >= 0}?.let {Log.i(TAG, "testTakeIf: has yan")}?: Log.i(TAG, "testTakeIf: no yan")

不过不建议这样做,这样不仅增加了代码理解难度,而且后续维护也比较难(?:后面只能跟一个语句),还不如直接用作用域函数+判断:

        name.indexOf("yan").let {Log.i(TAG, "testTakeIf: it = $it")if (it >= 0) {Log.i(TAG, "testTakeIf: has yan")} else {Log.i(TAG, "testTakeIf: no yan")}}

以上代码地址

总结

  • takeIf和takeUnless作用:根据代码块里面的返回值,决定返回空还是this本身,配合?.作用域函数来做判断
  • 使用场景:只需要单个if分支语句的时候
  • 优点
    • 可以配合其他作用域函数返回的结果,做出单向判断,保持链式调用
    • 简化写法,逻辑清晰,减少代码量,代码更优雅
  • 缺点
    • 如果返回值和takeXx写在一起时,debug无法进去看到it的值
    • 提升代码阅读者的理解难度

上述意见乃是个人经验之谈,如果错漏,敬请指正

Kotlin里的takeIf和takeUnless相关推荐

  1. Kotlin 中的 run、let、with、apply、also、takeIf、takeUnless 语法糖使用和原理分析

    这些Kotlin的语法糖函数经常用,但也很容易搞混,所以转载一下,若混了可以回来再看 转载自公众号:纸上浅谈 正文: 在 Kotlin 有一些可以简化代码的语法糖,比如 run.let.with.ap ...

  2. Kotlin 源码里成吨的 noinline 和 crossinline 是干嘛的?看完这个视频你转头也写了一吨...

    视频先行 扫码看视频吧! 然后下面的就不用看了 或者--你喜欢看文字? Kotlin 里有个特别好用的关键字叫 inline,它可以帮你对做了标记的函数进行内联优化.所谓内联就是,调用的函数在编译的时 ...

  3. Kotlin学习笔记

    文章目录 1.空检查 2.数据类型 3.in表达式 4.when表达式 5.字符串模板 6.函数头 7.默认参数 8.具名参数 9.Unit类型 10.Nothing类型特点 11.反引号函数名 12 ...

  4. kotlin需要注意的知识点

    字符串模板  "$var" lambda表达式跳出循环,需要设置标记.否则跳出当前函数 array.forEach forEach@{ if(it == 'b') return @ ...

  5. Kotlin系列四:标准函数、扩展函数、高阶函数、内联函数

    目录 一 标准函数 1.1 作用域函数 1.1.1 let 1.1.2  with 1.1.3 run 1.1.4 apply 1.1.5 also 1.1.6 takeIf 与 takeUnless ...

  6. 学习kotlin笔记之一

    各个语言的精华集聚一身的新时代语言Kotlin,Google下定决心,将kotlin作为Android原生语言. 1.变量空指针检查: (1)变量直接赋值为null,不允许,会检查报错.所以想要赋值为 ...

  7. Kotlin中的高阶函数

    博客地址sguotao.top/Kotlin-2018- 在Kotlin中,高阶函数是指将一个函数作为另一个函数的参数或者返回值.如果用f(x).g(x)用来表示两个函数,那么高阶函数可以表示为f(g ...

  8. Kotlin学习笔记30 补充 作用域函数

    参考链接 https://www.kotlincn.net/docs/reference/scope-functions.html 背景介绍 1.本节主要讲述几个Kotlin库提供的几个方便的方法 l ...

  9. Kotlin StandardKt 标准库源码走一波

    距离上篇Kotlin文章,应该有差不多半年时间.没别的原因,因为,懒,而且,想产出一篇稍微质量好的博客好难. 最近在研究Python,所以最近也可能会更新一些Python的学习笔记. Standard ...

  10. 《Kotlin 程序设计》第十二章 Kotlin的多线程:协程(Coroutines)

    第十二章 Kotlin的多线程:协程(Coroutines) Kotlin 1.1 introduced coroutines, a new way of writing asynchronous, ...

最新文章

  1. 原生CSS设置预加载图片之前的默认背景图
  2. Mozilla Firefox 54 今起支持开启e10s多进程功能
  3. jstl:sql标签介绍
  4. 通过计算机二级考试的计划,如何轻松通过国家计算机二级考试
  5. 分布式缓存的面试题9
  6. 前端学习(3248):react的生命周期getSnapBeforeUpdate举例
  7. POJ 1330:Nearest Common Ancestors【lca】
  8. 对“被投诉”的最新解读(外四篇)
  9. 绝对路径、相对路径详解
  10. Ubuntu 16.04 安装 搜狗输入法 sogou input
  11. 知行EDI系统-入门篇
  12. HTML5 QQ登录背景动态图片
  13. Apache虚拟主机的三种方式
  14. 基于Multisim的波形发生器
  15. xlsx文件 wps 可以打开 excel 打不开
  16. OpenCV如何去除图片中的阴影
  17. matlab画椭圆抛物面参数方程,求单叶双曲面和双叶双曲面、椭圆抛物面、双曲抛物面用matlab怎么画或其参数方程?...
  18. 软件著作权(软著)申请之六大坑
  19. iOS开发常用知识点(持续更新2018.6.25)
  20. 数据预处理与特征工程—9.Lasso算法实现特征选择

热门文章

  1. SPA是什么及原生js实现简易SPA单页面
  2. 如何使用eclipse运行一个简单的java程序
  3. c语言实现mysql通配符_Mysql的C语言接口简单实现电话本功能
  4. 程序员福利:当编程语言都变成女孩子
  5. 百度地图根据经纬度获取实际地理位置Api接口
  6. HubilderX更新记录
  7. CRM客户关系管理系统助力企业处理客户投诉问题
  8. “时间的朋友”2017跨年演讲全回顾
  9. 英语AquilariaCrassna奇楠沉香
  10. 蓝韵DR采集工作站LINUX系统,蓝韵PACS系统的技术参数