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"
}
複製代碼
相關文章
相關標籤/搜索