說說kotlin中的作用域函數

本篇文章主要分享一下Kotlin的作用域函數let, run, with, apply和also的用法及區別。

作用域函數在執行過程中,通過lambda 表達式,形成一種臨時性的作用域,可以減少部分邏輯代碼的數量。

上下文對象:this or it

this

run、with 以及 apply 通過關鍵字 this 引用上下文對象。因此,在它們的 lambda 表達式中可以像在普通的類函數中一樣訪問上下文對象。

it

let 及 also 將上下文對象作爲 lambda 表達式參數。如果沒有指定參數名,對象可以用隱式默認名稱 it 訪問。it 比 this 簡短,帶有 it 的表達式通常更容易閱讀。

返回值

  • apply 及 also 返回上下文對象。
  • let、run 及 with 返回 lambda 表達式結果.

let函數

let函數在日常開發中經常用到,一般用於非空判斷以用於後序的操作使用?.,上下文對象{it} 作爲lambda表達的參數,表示lambda的返回值。

data class User(var name: String)
fun main() {
    val user = User("Wangwei")
    //let 和run都會返回閉包的執行結果,區別在於let有閉包參數, 而run沒有閉包參數
    val letResult: String = user.let { user: User -> "let::${user.javaClass}" }
    // let中只有一個參數時,閉包參數可以省略,可以用it代替
    val letResults: String = user.let { "let::${it.javaClass}" }
    println(letResult)
    
    var str :String? = "hello"
    // 如果str的值爲null, 則let中的函數不會執行
    str?.let {
        println(it.length)
    }
    
    // 用於鏈式調用結果
    val numbers = mutableListOf<String>("one","two","three","four","five")
    numbers.map { it.length }.filter { it > 3 }.let {
        println(it)
    }
}

with函數

是一個非擴展函數,調用同一個對象的多個方法或屬性, 省去對象名重複,直接調用方法名和屬性, 上下文對象爲 this

val numbers = mutableListOf<String>("one","two","three","four","five")   

with(numbers) {
    println("with argument is $this")
    println("it contain $size element")
    //println("it contain ${this.size} element") 和上面一行效果一致
}

run函數

上下文對象是this, 返回lambda對象,結合了let,with的作用,調用同一對象的多個方法和屬性, 省去對象名重複調用, 直接調用屬性和方法名,統一做判空處理。

numbers.run {
        println("with argument is $this")
        println("it contain $size element")
    }

    var str1 :String? = "hello"
    str1?.run { 
        println("str1 length is $length")
        println("char is ${get(1)}")
    }

apply函數

上下文對象是 this, 返回值是對象本身,可以在對象上連續鏈式調用。主要用於對象初始化時進行屬性賦值。

data class Person(var name: String, var age: Int = 0, var city: String = ""){}
var testUser = Person("小明").apply {
        age = 18
        city = "上海"
    }
    println(testUser)

also函數

上下文對象 作爲lambda表達式參數{it} 使用, 和let參數比較相似

val numbers = mutableListOf<String>("one","two","three","four","five")

numbers.also {
    println("with argument is $it")
    println("it contain ${it.size} element")
}.add("哈哈")

作用域函數如何選擇

  • 對一個非空(non-null)對象執行 lambda 表達式:let
  • 將表達式作爲變量引入爲局部作用域中:let
  • 對象配置:apply
  • 對象配置並且計算結果:run
  • 在需要表達式的地方運行語句:非擴展的 run
  • 附加效果:also
  • 一個對象的一組函數調用:with

takeIf與taceUnless

進行對象檢測過濾,開發中常與上述的作用域函數結合使用。

//takeIf的閉包返回一個判斷結果, 爲false時,takeIf函數返回空
//takeUnless 與 takeIf 剛好相反, 閉包的判斷結果,爲true時函數會返回空
user.takeIf { it.name.length > 0 }?.also { println("姓名爲${it.name}") } ?: println("姓名爲空")
user.takeUnless { it.name.length > 0 }?.also { println("姓名爲空") } ?: println("姓名爲${user.name}")

今天是週末,各位讀者週末愉快。

--- End ---


本文分享自微信公衆號 - 君偉說(wayne90214)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章