Kotlin中的also、let、run、with、apply函数的用法

在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

  • let
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

若是咱们要用run函数实现与let同样的功能,应该是这样的:对象

Book("《海边的卡夫卡》", "村上春树", 59).run {
    println(this)
    this.adjust(-5)
    println(this)
  }
复制代码

能够看出来,run更像是Book对象的扩展函数,即:block: T.()。他是将this做为参数传递,在大多数状况下this能够被省略,所以咱们能够更加关注内部实现。string

  • with

一样的,若是要实现上述目的,咱们使用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)
  }
复制代码
  • also

上面咱们说到了,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

对于apply函数来讲,传递的参数是this, 返回值也是this。固然apply还有另外一个做用,就是能够轻松的实现Builder模式(这里咱们使用另外一个对象Persion):

Persion().apply{
    name = "小明"
    age = "13"
    brithday = "2000-01-01"
}
复制代码
相关文章
相关标签/搜索