在Kotlin中有几个十分类似的标准库函数,他们之间也有一些差别,若是使用不当可能回获得与预期相反的效果,因此咱们来简短的区分一下let、also、run、with、apply 这5个标准库函数的区别。 Kotlin提供了这几种标准域函数主要是为了简化一些操做,让代码看起来更加的简洁,可读性更好。app
在最开始咱们先建立一个简单的Book类,做为例子咱们来看看每种函数的不一样函数
data class Book(var name: String, var author: String, var price: String){
fun adjust( value: Int){
price = price.plus(value)
}
}
fun main(){
}
复制代码
上述是一个很是简单的Book类,包括三个属性:书名、做者、价格。而后有一个调整价格的方法。ui
Book("《海边的卡夫卡》", "村上春树", 59).let {
println(it)
it.adjust(-5) //let的参数为it,也就是自身
println(it)
}
复制代码
在Book类的main函数中添加上述代码,而且运行,结果以下:this
Book(name=《海边的卡夫卡》, author=村上春树, price=59) Book(name=《海边的卡夫卡》, author=村上春树, price=54)spa
在上述代码中,咱们能够看到let的参数为自身,即:block: .(T)
,将自身做为参数传递。code
若是咱们要用run函数实现与let同样的功能,应该是这样的:对象
Book("《海边的卡夫卡》", "村上春树", 59).run {
println(this)
this.adjust(-5)
println(this)
}
复制代码
能够看出来,run更像是Book对象的扩展函数,即:block: T.()
。他是将this做为参数传递,在大多数状况下this能够被省略,所以咱们能够更加关注内部实现。string
一样的,若是要实现上述目的,咱们使用with应该是这样的:it
with(Book("《海边的卡夫卡》", "村上春树", 59)){
println(this)
this.adjust(-5)
println(this)
}
复制代码
这里要说明的一点是,with与其他4个库函数最大的不一样就在于with不是一个扩展函数。with是一个普通函数,那么若是咱们在with中传递了一个可为空的参数时,with函数将会变成:io
val book: Book? = Book("《海边的卡夫卡》", "村上春树", 59)
with(book){
println(this)
this!!.adjust(-5) //将空判断放在了with方法内部
println(this)
}
复制代码
能够看到咱们是将空判断放在了with内部,显然这样不是一个很是好的实现,若是咱们使用run,就能够很方便的解决这个问题:
val book: Book? = Book("《海边的卡夫卡》", "村上春树", 59)
book?.run{
println(this)
this.adjust(-5)
println(this)
}
复制代码
上面咱们说到了,let与run的区别就在于传递的参数不一样,那么let与also的区别就在于返回值的不一样,他们的参数都是it,可是let返回的是lamda表达式的结果。而also返回的是上下文,即:this。 咱们看一下下面的代码。
Book("《海边的卡夫卡》", "村上春树", 59)
.let {
println(it)
it.adjust(-5)
it //由于adjust()方法没有返回值,咱们须要将调整价格后的Book对象做为lamda表达式的返回值返回
}
.let {
print(it)
}
Book("《海边的卡夫卡》", "村上春树", 59)
.also {
println(it)
it.adjust(-5) // 因为also直接返回当前对象,因此咱们不用再提供返回值
}
.let {
print(it)
}
复制代码
上述两段代码都输出:
Book(name=《海边的卡夫卡》, author=村上春树, price=59) Book(name=《海边的卡夫卡》, author=村上春树, price=54)
若是咱们将第一段代码中的第一个let{}中最后一个it返回值去掉,则会输出:
Book(name=《海边的卡夫卡》, author=村上春树, price=59)
Kotlin Unit
能够看到,let输出的是lamda表达式的值,而also的返回值是this. 经过also与let的配合,咱们能够写出一些可读性更强的链式调用的语句。
对于apply函数来讲,传递的参数是this, 返回值也是this。固然apply还有另外一个做用,就是能够轻松的实现Builder模式(这里咱们使用另外一个对象Persion):
Persion().apply{
name = "小明"
age = "13"
brithday = "2000-01-01"
}
复制代码