本篇文章主要分享一下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源創計劃”,歡迎正在閱讀的你也加入,一起分享。