作用域函数,就是些技巧性方法,函数定义全在Standard.kt文件里。本篇,用实例记录一下它们的用法。
1.所谓作用域函数:它们的lamda函数作用域===对象类内部作用域。 就像是对象类的内部方法一样。
这样在lamda函数内,可以直接调用对象的方法,属性,不需要通过对象实例点出方法,属性。
2. let/takeIf/takeLess, 需要it引导
3. with是独立函数,其他函数都可由对象点出来。
- val list = listOf("apple", "orange", "pear")
- val result = StringBuilder().run {
- append("Start eating fruits.\n")
- for (fruit in list){
- append(fruit).append("\n")
- }
-
- append("Ate all fruits.")
-
- toString()
- }
-
- println(result)
- fun main() {
- val user = User("alan", 18)
- val applyResult = user.apply {
- //这儿都是user对象的作用域
- age = 20
- }
- println(applyResult) //输出:User(name=Peter, age=20)
- println(user) //输出:User(name=Peter, age=20)
- println(applyResult === user) //输出:true
- }
-
- data class User(var name: String, var age: Int)
第二个例子:
- val list = listOf("apple", "orange", "pear")
- val result = StringBuilder().apply{
- append("Start eating fruits.\n")
- for (fruit in list){
- append(fruit).append("\n")
- }
-
- append("Ate all fruits.")
- }
-
- println(result.toString())
- val list = listOf("apple", "orange", "pear")
- val result = with(StringBuilder()) {
- append("Start eating fruits.\n")
- for (fruit in list){
- append(fruit).append("\n")
- }
-
- append("Ate all fruits.")
-
- toString()
- }
-
- println(result)
- object.let{
- it.todo()//在函数体内使用it替代object对象去访问其公有的属性和方法
- ...
- }
-
- //另一种用途 判断object为null的操作
- object?.let{//表示object不为null的条件下,才会去执行let函数体
- it.todo()
- }
下面的写法,有点罗嗦,如果使用user的参数方法更多,就要被问号烦死了。
- fun doStudy(user:User?){
- user?.age = 20
- user?.name = "alan"
- }
或者用if判空:
- fun doStudy(user:User?){
- if(user != null){
- user.age = 20
- user.name = "alan"
- }
- }
用let函数简化:
- fun doStudy(user:User?){
- user?.let{
- it.age = 20
- it.name = "alan"
- }
针对if判空那种方式,是有问题的。当User对象是全局对象的时候。就编译错误了。提示有多线程问题。
- var user:User? = null
- fun doStudy() {
- if (user!=null) {
- user.age = 20 //编译错误提醒
- user.name = "alan"//编译错误提醒
- }
- }
一般可用于多个扩展函数链式调用。
- fun main() {
- val user = User("alan", 18)
- val alsoResult = user.also {
- println("user 之前的名字是:${it.name}") //user 之前的名字是:alan
- }.apply {
- name = "lin"
- }
- println(alsoResult) //User(name=lin, age=18)
- println(user) //User(name=lin, age=18)
- println(alsoResult === user) //true
- }
-
- data class User(var name: String, var age: Int)
takeIf,takeunless, 区别就只有一个是满足代码块里面的条件才返回对象本身,一个是不满足条件才返回。
下面三段代码都是等价的:
用if语句:
- fun testWithoutTakeIf() {
- val name = "alan Gong"
- val hasGong = name.indexOf("Gong")
- Log.i(TAG, "testWithoutTakeIf: hasGong = $hasGong")
- if (hasGong >= 0) {
- Log.i(TAG, "testWithoutTakeIf: has Gong")
- }
- Log.i(TAG, "testWithoutTakeIf: $name")
- }
-
- 输出:
- I: testWithoutTakeIf: hasGong = 0
- I: testWithoutTakeIf: has Gong
- I: testWithoutTakeIf: alan Gong
用takeIf:
- fun testTakeIf() {
- val name = "alan Gong"
- name.indexOf("Gong")
- .takeIf {
- Log.i(TAG, "testTakeIf: it = $it")
- it >= 0
- }
- ?.let {
- Log.i(TAG, "testTakeIf: has Gong")
- }
- Log.i(TAG, "testTakeIf: $name")
- }
-
- 输出:
- I: testTakeIf: it = 0
- I: testTakeIf: has Gong
- I: testTakeIf: alan Gong
用takeLess: 注意函数体的判断和takeIf函数体里相反。
- fun testTakeUnless() {
- val name = "alan Gong"
- name.indexOf("Gong")
- .takeUnless {
- Log.i(TAG, "testTakeUnless: it = $it")
- it < 0
- }
- ?.let {
- Log.i(TAG, "testTakeUnless: has Gong")
- }
- Log.i(TAG, "testTakeUnless: $name")
- }
-
- 输出:
- I: testTakeUnless: it = 0
- I: testTakeUnless: has Gong
- I: testTakeUnless: alan Gong
由上面的简单例子也可以看出,这两个通常和其他作用域函数,组成链式调用。
- repeat(3){
- println("repeat")
- }
好了,目前所有的作用域函数都记录清楚了。看起来是挺强大的,但是这种东西多了,可读性就不见得好了。另外还有一张网络上的总结图:
