Kotlin作用域函数及用法

前言

Kotlin 标准库包含几个函数,它们的唯一目的是在对象的上下文中执行代码块。当对一个对象调用这样的函数并提供一个lambda 表达式时,它会形成一个临时作用域。在此作用域中,可以访问该对象而无需其名称。这些函数称为作用域函数。共有以下五种:letrunwithapply 以及 also

以上是官网对Kotlin作用域的一个解释,读几遍是不是也不懂他意思?

从实际出发,依次展开来看看。

let

在作用域中使用(it)来访问对象,返回值是lambda 表达式的结果。

fun main() {
    var name="name"
    println(name.let {
        it.length
    })
}
复制代码

如上操作,在{}号中,有个隐式的变量名it,在其中对name变量的任何操作都可以使用it来代替,如果在其中更改了对象的值,那么it变量是不会发生改变的。

并且最后一行的返回结果,会作为let函数的返回结果。如果最后一行没有返回值,在Kotlin中也会被kotlin.Unit来代替。

run

在作用域中使用(this)来访问对象,返回值是lambda 表达式的结果。

fun main() {
    var name="name"

    println(name.run {
        println(length)
        "a"
    })
}
复制代码

如上操作,除了返回值和let一样,他的作用域变量成为了this,但是这里就发生了一个变化,对对象的操作可以不加this,直接可以调用,而let中不行,比如上面的操作,如果用let来访问length方法时,就必须是it.length,在看一个例子,

class Data(var name: String) {
}
fun main() {
    var name = "name"
    println(Data("dog").run {
        println(name)
        name="cat"
    })
    println(name)
}
复制代码

run还有一个非扩展方法,调用也不需要什么参数,返回值Lambda 表达式结果,如下。

fun main() {
    var function = {
        println("a")
    }
//    function()
    run(function)
}
复制代码

在Java中,方法中写的{}会自动执行,而kotlin不会,需要手动调用,或者是run。

with

他不是扩展函数,也就是没有obj.with这种写法,而是with(obj){},然后在lambda表达式内部,可以使用(this)访问此对象,也可以省略, 返回值是lambda 表达式结果。

with可以理解为"对于这个对象,执行以下操作"。

var name="cat"
with(name){
    name="dog"
    println(name)
    println(this)
}
复制代码

同样,在作用域中对原对象修改后,并不影响其中的this。

apply

在作用域中使用(this)来访问对象,返回值是是对象本身。

class Data(var name: String) {
}
fun main() {
    var name = Data("dog").apply {
        name = "cat"
    }
    println(name.name)
}
复制代码

also

在作用域中使用(it)来访问对象,返回值是是对象本身。

class Data(var name: String) {
}
fun main() {
    var name = Data("dog").also {
       it.name="cat"
    }
    println(name.name)
}
复制代码

总结

看了这么多,是不是还迷迷糊糊的,这些作用域函数都非常相似,因此了解它们之间的区别很重要,我们可以从他们这两点区分。

  • 引用上下文对象的方式
  • 返回值
函数 对象引用 返回值 是否是扩展函数
let it Lambda 表达式结果
also it 上下文对象 mps
run this Lambda 表达式结果
with this Lambda 表达式结果 不是:把上下文对象当做参数
apply this 上下文对象
run - Lambda 表达式结果 不是:调用无需上下文对象

最重要的就是记住返回值,因为对象引用的方式不太重要,如果你想少写代码,并且返回值需要Lambda 表达式结果,那么就使用run,如果需要本身,那就使用apply。

我们在看一个例子。

public class MainJava {
    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream("/home/HouXinLin/1.txt")));
        String temp = null;
        while ((temp = bufferedReader.readLine()) != null) {
            System.out.println(temp);
        }
    }
}
复制代码

而在Kotlin中while中又赋值又判断这种写法是错的,解决方式就需要使用作用域函数,并且接收的变量还需要设置为可空类型

fun main() {
    var bufferedReader = File("/home/HouXinLin/1.txt").inputStream().bufferedReader()
    var temp: String?
    while (bufferedReader.readLine().also { temp = it } != null) {
        println(temp)
    }
}
复制代码

猜你喜欢

转载自juejin.im/post/7048596405119778846
今日推荐