| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> 【对比Java学Kotlin】作用域函数 -> 正文阅读 |
|
[移动开发]【对比Java学Kotlin】作用域函数 |
什么是作用域函数?首先,落脚点是函数,什么的函数呢?能在某个上下文对象(可能是普通对象,也可能是个 Unit)的作用域内执行代码的函数。这里的作用域和 Java 的作用域有所不同,Java 的作用域更多的是指一对闭合的 {} 的内部区域:
变量独享其所在{}的区域,在这个区域内其他变量或方法都可以引用到这个变量,我们称之为作用域。
当然,不会使用作用域函数不影响使用 Kotlin,但是在某些情况下使用作用域函数会使我们的代码更加简洁,具有更好的可读性和可维护性。 使用方法我们举个最常见的例子,有一个 Person 类如下:
正常情况下我们可以执行如下操作:
等效地,我们可以使用作用域函数将上面的操作改写如下:
改写前后二者的执行结果完全一致。同时后者具有更好的可阅读性和简洁性,以及降低出错概率。之所以说可以降低出错概率,是因为往往我们在复制代码的过程中会手误造成错误,比如如下代码:
当我们写完 zhangsan,习惯性的复制出 lisi 的代码,但是在改名的时候却遗漏了其中的 除了 let,还有其他几个作用域函数,其主要区别在于在作用域内能引用当前对象的方式以及返回值。
使用场景如下述代码:
IDE 会报错:
这是因为,虽然我们给 name 赋了一个非空的值,但是由于代码块不是原子性的,不保证在执行 name.length 时 name 已经是 null 了,可能发生空指针异常。 这个时候,我们可以使用 let 函数对上述代码改造以避免报错:
之所以这么写不会报错,是因为 let 代码块里面的 it 变量是 final 的,我们可以运行如下代码进行试验:
直接给 it 赋值会导致编译报错,报错信息如下:
也就是说,当执行完 ?. 之后传入 let {} 内的是 name 变量非空时的快照,就是一个值,不会为 null,且不能改变。 大家有没有联想到什么?是不是跟 Java 里面的匿名内部类引用外部的变量必须是 final 的原理有点类似?详见 Java 匿名内部类中的外部引用为什么必须是 final 的? 这种写法也一定程度上消灭了可恶的 if-else。 letlet 一般用于非空的对象上,比如上面我们提到的
注意,let 返回的是 lambda 表达式的结果,上述代码返回的是 Unit。如果我们想让 zhangsan 是 moveTo() 以及 incrementAge() 之后的 Person,我们应该:
applyapply 主要用于配置对象内的属性,比如初始化,在内部以 this 指针引用当前对象,或者我们也可以把 this 指针省略掉。因为其返回值是当前对象,所以特别适合在新建对象的时候使用,字面意思,apply 的意思是 “apply the following assignments to the object”,比如:
also使用 this 引用上下文对象,返回值是该对象本身。根据其含义 “and also do the following with the object.”,多用于打印日志或执行方法。
run使用 this 引用上下文对象,返回值是 lambda 表达式的结果。
withwith 通过 this 引用对象,返回的是 lambda 的结果。最好使用 with 调用对象的方法,而不要返回值,with 的意思是 “with this object, do the following”:
注意,我们在讨论的过程中,是没有限定上下文对象非空的,即,在空对象上也能执行这些作用域函数:
输出: 而如果我们加上对其中一个加上?,则对应的作用域函数不会执行:
输出: 作用域函数不仅可以作用在变量上,也可以作用在 Unit 上:
输出: takeIf & takeUnless出了上述作用域函数,Kotlin 的标准库还提供了 takeIf() 和 takeUnless() 方法,以方便在链式调用中检查对象的状态。 如果为 true,takeIf 返回当前对象,否则返回 null。相反的,如果为 false,takeUnless 返回当前对象,否则返回 null:
takeIf 和 takeUnless 一般和作用域函数结合使用,先用 takeIf 和 takeUnless 过滤出我们关心的对象,然后使用 ?.let 去操作这些对象。
参考文章 |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 | -2025/1/31 6:27:09- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |