Kotlin的作用域函数有5个之多,让人一开始都不知道怎么去用他们,下面我来用简单明了的例子来告诉你们他们的区别和适用场景。
Kotlin标准库包含⼏个函数,它们的唯⼀⽬的是在对象的上下⽂中执⾏代码块。每个作用域函数有两个主要区别:引⽤上下⽂对象的⽅式和返回值。
一、按对象的方式区分:
run 、with 以及 apply 通过关键字 this 引⽤上下⽂对象。因此,在它们的 lambda 表达式中可以像在普通的类函数中⼀样访问上下⽂对象。适用于主要对对象成员进⾏操作(调⽤其函数或赋值其属性)的 lambda 表达式。
反过来,let 及 also 将上下⽂对象作为 lambda 表达式参数。当调⽤对象函数或属性时,不能像 this 这样隐式地访问对象。因此,适用于当上下⽂对象在作⽤域中主要⽤作函数调⽤中的参数时。
下面上代码
val testInfo = TestInfo("N", ObservableInt(0))
testInfo.apply { this.name }//run 、with 以及 apply可以这样用
testInfo.apply { name }//也可以省略this这样用
testInfo.let { it.name }//let 及 also可以这样用
testInfo.let { name }//let 及 also不可省略、隐式地访问对象
run 、with 以及 apply主要这样用
testInfo.run {
this.name="A"//赋值其属性
}
b.rvMain.run {
adapter=myAdapter//赋值其属性
layoutManager=LinearLayoutManager(this@MainActivity)//赋值其属性
clearOnScrollListeners()//调⽤其函数
}
let 及 also 主要这样用
testInfo.let {
letLog(it.name)//函数调⽤中的参数
Log.i(TAG, "onCreate: ${it.name}")//函数调⽤中的参数
}
fun letLog(s: String) {
Log.i(TAG, "letLog: $s")
}
二、根据返回结果,作⽤域函数可以分为以下两类:
apply 及 also 返回上下⽂对象。 因此,它们可以作为辅助步骤包含在调⽤链中:你可以继续在同⼀个对象上进⾏链式函数调⽤。
let 、run 及 with 返回 lambda 表达式结果。所以,在需要使⽤其结果给⼀个变量赋值,或者在需要对其结果进⾏链式操作等情况下,可以使⽤它们。
下面上代码
apply 及 also 主要这样用,因为返回上下⽂对象,所以可以继续在同⼀个对象上进⾏链式函数调⽤。
testInfo.also { Log.i(TAG, "onCreate: ${it.name}") }
.apply { this.name = "B" }.also {
Log.i(TAG, "onCreate: ${it.name+it.i}")
}
let 、run 及 with 主要这样用,返回lambda 表达式的结果。
with(testInfo){
this.name="C" //返回Unit
}.let { it.i }//代码错误,因为返回的是一个Unit
with(testInfo) {
this.name = "C"
name//返回name
}.let {
it.equals("C")//返回boolean
}.run { if (this) Log.i(TAG, "it is C") }
总结
let:适用于函数调⽤中的参数或者在需要对其结果进⾏链式操作。(it,返回 lambda 表达式结果)
also:let函数的可同对象链式函数调⽤版。(it, 返回上下⽂对象)
with:适用于let函数任何场景和对对象成员进⾏操作(调⽤其函数或赋值其属性)的 lambda 表达式,除了不是拓展函数,this 引⽤上下⽂对象,可以省略 this,来让你的代码更简短。(this,返回 lambda 表达式结果)
run:with函数的扩展函数版。(this,返回 lambda 表达式结果)
apply:run函数的可同对象链式函数调⽤版。(this, 返回上下⽂对象)
本文根据Kotlin官方文档和自己的理解编写