kotlin的標準函數,指的是Standard.kt文件中定義的函數,包括let、also、with、run、apply函數。
1.let函數
let擴展函數的實際上是一個作用域函數,當你需要去定義一個變量在一個特定的作用域範圍內,let函數的是一個不錯的選擇;let函數另一個作用就是可以避免寫一些判斷null的操作。
適用場景
場景一: 最常用的場景就是使用let函數處理需要針對一個可null的對象統一做判空處理。
//沒有let函數,需要每次判空,代碼不夠優雅
data?.toString()
data?.toString()
data?.toString()
data?.let {
//在函數域中,保證data對象不爲,不用多次去判空
it.toString()
it.toString()
it.toString()
}
場景二: 然後就是需要去明確一個變量所處特定的作用域範圍內可以使用
data.let {
//在函數體內使用it替代該data對象使用
it.toString()
}
2.also函數
also函數使用的一般結構
object.also{
}
適用於let函數的任何場景,also函數和let很像,只是唯一的不同點就是let函數最後的返回值是最後一行的返回值而also函數的返回值是返回當前的這個對象。
user?.also {
it.age = 18
it.name = "小明"
}.age
3.with函數
with函數使用的一般結構
with(object){
//todo
}
它是將某對象作爲函數的參數,在函數塊內可以通過 this 指代該對象。
適用場景
需要設置某個對象多個屬性到UI上時,需要不斷調用對象,使用with函數能避免對象的重複書寫。
data class User(var name: String, var age: Int)
with(user){
Log.i("TAG", "age=$age")
Log.i("TAG", "name=$name")
}
該age和name變量就是該with參數中的user對象的屬性值。
4.run函數
run函數使用的一般結構
object.run{
}
適用場景
適用於let,with函數任何場景。因爲run函數是let,with兩個函數結合體,準確來說它彌補了let函數在函數體內必須使用it參數替代對象,在run函數中可以像with函數一樣可以省略,直接訪問實例的公有屬性和方法,另一方面它彌補了with函數傳入對象判空問題,在run函數中可以像let函數一樣做判空處理。
user?.run {
Log.i("TAG", "age=$age")
Log.i("TAG", "name=$name")
}
1.全局函數run 替代 java中 { } 代碼作用域
在一個作用域中,創建一個類對象不能定義重名,也許會定義爲如下情況:
var user1 = User()
user1.age = 20
var user2 = User()
user2.age = 21
var user3 = User()
user3.age = 22
kotlin語法層面不支持代碼作用域,可以通過run函數替代,創建多個作用域,使變量名能夠只在自己的作用域中生效。
kotlin.run {
var user = User()
user.age = 20
}
kotlin.run {
var user = User()
user.age = 21
}
kotlin.run {
var user = User()
user.age = 22
}
2.用於省略函數返回類型
fun getUser() : User {
return User()
}
fun getUser2() = kotlin.run { User() }
在run函數當中它不僅僅只是一個作用域,他還有一個返回值。他會返回在這個作用域當中的最後一個對象。
例如現在有這麼一個場景,用戶領取app的獎勵,如果用戶沒有登錄彈出登錄dialog,如果已經登錄則彈出領取獎勵的dialog。我們可以使用以下代碼來處理這個邏輯。
var dialogLogin = Dialog(this)
var dialogPay = Dialog(this)
var isLogined = false
kotlin.run {
if (isLogined) {
dialogLogin
} else {
dialogPay
}
}.show()
5.apply函數
apply函數使用的一般結構
object.apply{
}
從結構上來看apply函數和run函數很像,唯一不同點就是它們各自返回的值不一樣,run函數是以閉包形式返回最後一行代碼的值,而apply可以任意調用該對象的任意方法,並返回該對象。
適用場景
整體作用功能和run函數很像,唯一不同點就是它返回的值是對象本身,而run函數是一個閉包形式返回,返回的是最後一行的值。
場景一:apply一般用於一個對象實例初始化的時候,需要對對象中的屬性進行賦值。
data class User(var name: String, var age: Int)
ArrayList<User>().apply {
add(User("小明", 18))
add(User("小王", 16))
}.run {
get(0)
}
創建User對象並添加入集合,添加完成後取出第一個對象。
場景二:多層級判空問題
data class Response(var code: Int, var data: Data)
data class Data(var icon: String, var title: String)
response?.apply {
//response不爲空時可操作response
}.data?.apply {
//data不爲空時可操作data
}.title?.apply {
//title不爲空時可操作title
}
let,with,run,apply,also函數總結:
函數名 | 函數體內使用的對象 | 返回值 | 適用場景 |
---|---|---|---|
let | it指代當前對象 | 返回任意類型R | 適用於處理多處判空的場景 |
also | it指代當前對象 | 返回this | 適用於let函數的任何場景,一般可用於多個擴展函數鏈式調用 |
with | this指代當前對象或者省略 | 返回任意類型R | 適用於調用同一個類的多個方法、屬性時,省去每次書寫類名 |
run | this指代當前對象或者省略 | 返回任意類型R | 適用於let,with函數任何場景 |
apply | this指代當前對象或者省略 | 返回this | 適用於run函數任何場景,一般可用於多個擴展函數鏈式調用 |