柚子快報(bào)邀請碼778899分享:76.Kotlin擴(kuò)展函數(shù)簡介
第一部分:Kotlin 擴(kuò)展函數(shù)簡介
Kotlin 語言自帶很多擴(kuò)展函數(shù),它們通過在已有類型上擴(kuò)展新的作用域函數(shù)(scope function)來改善代碼可讀性與簡潔性。這些擴(kuò)展函數(shù)不僅能夠改善代碼風(fēng)格,同時(shí)還能提供鏈?zhǔn)秸{(diào)用的便利。常見的擴(kuò)展函數(shù)有:
letalsoapplyrunwith
這些擴(kuò)展函數(shù)可以讓我們在對象上執(zhí)行一些額外操作,同時(shí)還允許我們避免樣板代碼(boilerplate)和顯式的數(shù)據(jù)傳遞。每個(gè)函數(shù)在設(shè)計(jì)時(shí)都有其側(cè)重點(diǎn),以下將分別介紹。
第二部分:let 函數(shù)
2.1 let 函數(shù)的基本概念
let 是 Kotlin 中最常使用的擴(kuò)展函數(shù)之一,其標(biāo)準(zhǔn)定義如下(簡化示意):
public inline fun
簡單說,let 接受調(diào)用對象作為接收者,但在 lambda 表達(dá)式中,它以參數(shù) it(如果不定義參數(shù)名的話)傳入。let 會(huì)返回 lambda 表達(dá)式中的最后一行表達(dá)式的值。這說明它的返回值由 lambda 決定。
2.2 let 的參數(shù)傳遞方式
在 let 中,調(diào)用對象會(huì)被作為 lambda 的唯一參數(shù)傳遞進(jìn)去,該參數(shù)默認(rèn)命名為 it(你也可以自己命名)。因此在 lambda 內(nèi)部,若你需要引用調(diào)用對象,就需要使用 it。例如:
val name = "Alice"
val length = name.let {
println("當(dāng)前字符串:$it")
// 返回 it 的長度
it.length
}
在這個(gè)例子中,字符串 "Alice" 就是 let 調(diào)用的對象,并以 it 的形式傳入 lambda,最后返回值為 length。
2.3 let 的使用場景
非空判斷與安全調(diào)用 let 常常與空安全操作符(?.)搭配使用,可以避免空指針異常。例如:
val nullableName: String? = "Bob"
nullableName?.let {
println("非空字符串:$it")
// 可在空不為null時(shí)執(zhí)行更多操作
}
局部變量的作用域限制 let 函數(shù)可以用來將一段代碼包裹在一個(gè)局部作用域內(nèi),從而避免在代碼中引入過多的局部變量。 鏈?zhǔn)秸{(diào)用中的轉(zhuǎn)換 可以使用 let 在鏈?zhǔn)秸{(diào)用中轉(zhuǎn)換某個(gè)值,而不影響后續(xù)鏈?zhǔn)秸{(diào)用,比如計(jì)算值并返回最后結(jié)果。
2.4 let 的代碼示例
下面是一份完整的 Kotlin 文件,展示了 let 的使用以及詳細(xì)注釋說明:
package com.example.extensions
fun main() {
// 示例1:對非空字符串執(zhí)行操作
val name: String? = "Alice"
name?.let { nonNullName ->
println("Inside let: 當(dāng)前字符串是 $nonNullName")
// 返回處理結(jié)果,這里返回的是字符串長度
val length = nonNullName.length
println("字符串長度為 $length")
}
// 示例2:用于鏈?zhǔn)秸{(diào)用,轉(zhuǎn)換數(shù)據(jù)類型
val originalValue = "12345"
val processedValue: Int = originalValue.let {
println("轉(zhuǎn)換前的字符串:$it")
// 可以做一些轉(zhuǎn)換操作,比如轉(zhuǎn)換成 Int
it.toIntOrNull() ?: 0
}
println("轉(zhuǎn)換后的整型值為 $processedValue")
// 示例3:用作局部計(jì)算
val result = "Hello, World!".let {
println("字符串是:$it")
// 可以返回任意類型
"$it - Processed"
}
println("let 返回的結(jié)果:$result")
}
2.5 總結(jié) let
let 的參數(shù)以 it 的形式傳遞,也可以指定名稱。返回 lambda 表達(dá)式最后一行的值。主要用途在于進(jìn)行空值判斷、值轉(zhuǎn)換和局部作用域的封裝。
第三部分:also 函數(shù)
3.1 also 函數(shù)的基本概念
also 的定義如下:
public inline fun
與 let 類似,also 通過 lambda 的參數(shù) it 接收對象。但與 let 不同的是,also 返回調(diào)用對象本身,而非 lambda 中最后行的值。因此也適用于鏈?zhǔn)秸{(diào)用。主要用于執(zhí)行額外操作,例如日志記錄、調(diào)試信息、或?qū)φ{(diào)用對象進(jìn)行一些額外不影響主要流程的處理。
3.2 also 的參數(shù)傳遞方式
在 also 中,調(diào)用對象同樣作為參數(shù)傳遞至 lambda 中,默認(rèn)名稱為 it。例如:
val number = 42
val sameNumber = number.also {
println("Logging number: $it")
}
這里,it 表示調(diào)用該擴(kuò)展函數(shù)的對象,而整個(gè) also 調(diào)用最終返回 number 本身。
3.3 also 的使用場景
調(diào)試和日志記錄 also 常用于插入調(diào)試代碼或日志記錄,不改變對象數(shù)據(jù),但讓鏈?zhǔn)秸{(diào)用更易于閱讀。 附加操作 當(dāng)需要在對象上執(zhí)行額外操作,而不期望返回值變化時(shí),使用 also 是理想的選擇。例如,在對象構(gòu)造完成時(shí)記錄信息,再繼續(xù)使用該對象。
3.4 also 的代碼示例
如下代碼展示了 also 的一般用法:
package com.example.extensions
data class User(var username: String, var age: Int)
fun main() {
// 創(chuàng)建一個(gè) User 對象并在 also 中記錄日志
val user = User("Bob", 25).also {
println("創(chuàng)建 User 對象:$it")
}
// 也可以在鏈?zhǔn)秸{(diào)用中使用 also 保存中間結(jié)果
val result = "Kotlin".also {
println("原始字符串 $it")
}.uppercase()
println("經(jīng) uppercase 后結(jié)果:$result")
}
3.5 總結(jié) also
參數(shù)采用 it 傳遞,表示當(dāng)前對象。用于執(zhí)行額外操作(如日志記錄、驗(yàn)證等)。返回對象本身以便于鏈?zhǔn)秸{(diào)用,不會(huì)改變原始對象的值。
第四部分:apply 函數(shù)
4.1 apply 函數(shù)的基本概念
apply 是一個(gè)非常常用的擴(kuò)展函數(shù),其定義如下:
public inline fun
在 apply 中,調(diào)用對象作為 lambda 表達(dá)式的接收者(即 this),而不是作為參數(shù)傳遞。這意味著你可以直接使用 this 來訪問對象的屬性和方法,而且通??梢允÷?this 關(guān)鍵字,因?yàn)樵?lambda 內(nèi)部默認(rèn)就是當(dāng)前對象。apply 總是返回調(diào)用對象本身,非常適合于對象的初始化或配置。
4.2 apply 的參數(shù)傳遞方式
在 apply 中,lambda 的接收者為調(diào)用 apply 的對象。也就是說,lambda 內(nèi)部可以直接訪問對象的屬性和方法,而不用通過 it 來調(diào)用。例如:
val person = Person().apply {
name = "Charlie"
age = 30
}
在這里,name 和 age 是直接設(shè)置的,因?yàn)?this 被隱式地引用為 Person 對象。
4.3 apply 的使用場景
對象初始化和配置 apply 最常見場景就是在創(chuàng)建對象后對其屬性進(jìn)行初始化或配置。這樣可以減少樣板代碼并提高代碼可讀性。 構(gòu)建對象 當(dāng)構(gòu)建一個(gè)復(fù)雜對象時(shí),可以利用 apply 進(jìn)行屬性賦值操作,并返回構(gòu)建好的對象。
4.4 apply 的代碼示例
下面給出一個(gè)完整描述 apply 典型用法的示例代碼:
package com.example.extensions
data class Person(var name: String = "", var age: Int = 0)
fun main() {
// 使用 apply 配置 Person 對象
val person = Person().apply {
// 在 lambda 內(nèi)部直接訪問對象的屬性,這里的 this 指代 Person 對象
name = "Diana"
age = 28
println("Inside apply: name = $name, age = $age")
}
println("Configured Person: $person")
// 常用于鏈?zhǔn)秸{(diào)用初始化
val list = mutableListOf
add(1)
add(2)
add(3)
println("Inside apply, list: $this")
}
println("Final list: $list")
}
4.5 總結(jié) apply
使用 this 作為 lambda 接收者,可以直接訪問對象的屬性。主要用于對象初始化和配置,不改變返回值,始終返回同一對象。應(yīng)用場景包括構(gòu)建對象、設(shè)置屬性等操作。
第五部分:run 函數(shù)
5.1 run 函數(shù)的基本概念
run 是一個(gè)有兩種形式的擴(kuò)展函數(shù)。擴(kuò)展形式如下:
public inline fun
其非擴(kuò)展形式則是例如:
public inline fun
在擴(kuò)展形式中,run 與 apply 類似,也使用 this 作為 lambda 的接收者,但不同的是 run 返回 lambda 的最后一行表達(dá)式結(jié)果,而不是調(diào)用對象本身;這使得 run 更適合執(zhí)行一些計(jì)算,然后返回一個(gè)值。
在非擴(kuò)展形式中,run 可以用來執(zhí)行一段代碼塊,并返回計(jì)算結(jié)果,適用于那些需要將局部代碼塊的結(jié)果傳遞出去的場景。
5.2 run 的參數(shù)傳遞方式
在擴(kuò)展形式的 run 中,lambda 接收者為調(diào)用對象,使用 this 來引用對象,可以省略顯式的 this。在非擴(kuò)展形式中,代碼塊沒有接收者,純粹執(zhí)行一段代碼并返回值。
例如擴(kuò)展形式:
val person = Person("Eric", 35)
val description = person.run {
// this 默認(rèn)為 person
"Person: name = $name, age = $age"
}
非擴(kuò)展形式:
val sum = run {
val a = 10
val b = 20
a + b // 返回計(jì)算結(jié)果 30
}
5.3 run 的使用場景
對象上下文下計(jì)算結(jié)果 當(dāng)需要在對象上下文中計(jì)算并返回一個(gè)結(jié)果時(shí),用 run 更適合。例如,對象的狀態(tài)運(yùn)算或格式化結(jié)果返回。 臨時(shí)作用域封裝 非擴(kuò)展版的 run 可以作為一個(gè)代碼塊,把局部變量和計(jì)算封裝起來,防止污染外部作用域,并返回一個(gè)計(jì)算結(jié)果。
5.4 run 的代碼示例
下面展示 run 的擴(kuò)展和非擴(kuò)展使用場景:
package com.example.extensions
data class Person(var name: String, var age: Int)
fun main() {
// 擴(kuò)展形式 run:使用對象的上下文,返回 lambda 最后一行的值
val person = Person("Frank", 40)
val info: String = person.run {
println("Inside run: name = $name, age = $age")
"Person info: $name ($age years old)"
}
println("Run result: $info")
// 非擴(kuò)展形式 run:執(zhí)行一段代碼塊,返回代碼塊的計(jì)算結(jié)果
val result: Int = run {
val x = 100
val y = 50
println("Inside plain run: x = $x, y = $y")
x - y
}
println("Plain run result: $result")
}
5.5 總結(jié) run
擴(kuò)展形式:與 apply 類似,傳入對象上下文,返回 lambda 計(jì)算結(jié)果。非擴(kuò)展形式:無接收者,僅執(zhí)行一段代碼塊并返回結(jié)果。適用于需要在對象上下文中計(jì)算并返回結(jié)果或封裝一段獨(dú)立邏輯的場景。
第六部分:with 函數(shù)
6.1 with 函數(shù)的基本概念
with 是 Kotlin 中的一個(gè)標(biāo)準(zhǔn)庫函數(shù),其定義如下:
public inline fun
與 run 類似,with 將傳入的對象作為 lambda 的接收者(this)提供給代碼塊,但它不是作為擴(kuò)展函數(shù)調(diào)用,而是一個(gè)普通函數(shù)。它返回 lambda 表達(dá)式最后一行的結(jié)果。
6.2 with 的參數(shù)傳遞方式
在 with 中,第一個(gè)參數(shù)是傳入的對象,作為 lambda 的接收者(this)。在 lambda 內(nèi)部,不像 let 或 also 那樣依賴 it,而是通過 this(可以省略)直接訪問對象。
例如:
val person = Person("Grace", 27)
val result = with(person) {
println("Accessing within with: name = $name, age = $age")
"Person details: $name is $age years old"
}
6.3 with 的使用場景
對象操作封裝 當(dāng)需要對同一個(gè)對象進(jìn)行多次操作,且返回計(jì)算結(jié)果時(shí) with 是一種不錯(cuò)的選擇。與 run 的擴(kuò)展形式極為相似,但區(qū)別在于 with 是一個(gè)普通函數(shù),傳入對象后再調(diào)用代碼塊,可以讓代碼邏輯更清晰。 避免重復(fù)引用對象 在代碼塊內(nèi)直接使用對象,各個(gè)屬性及方法都可以直接操作,避免重復(fù)的對象引用。
6.4 with 的代碼示例
下面給出一個(gè)完整的示例,展示 with 的使用方法:
package com.example.extensions
data class Person(var name: String = "", var age: Int = 0)
fun main() {
val person = Person("Helen", 33)
// 使用 with 來對 person 對象進(jìn)行多次操作并返回計(jì)算結(jié)果
val detail = with(person) {
println("Inside with: name = $name, age = $age")
// 返回一個(gè)描述字符串
"Person Details: $name is $age years old."
}
println("With result: $detail")
}
6.5 總結(jié) with
通過普通函數(shù)傳入對象作為 receiver,將對象作為 lambda 中的 this。與 run(擴(kuò)展版)功能相似,但使用方式略有不同。適合用于封裝對單個(gè)對象的多次操作,并返回計(jì)算結(jié)果。
第七部分:各擴(kuò)展函數(shù)的對比與區(qū)別
經(jīng)過對 let、also、apply、run 和 with 的講解,我們可以總結(jié)出各擴(kuò)展函數(shù)主要的區(qū)別如下:
擴(kuò)展函數(shù)參數(shù)傳遞方式返回值主要用途常見場景l(fā)et以 it 傳遞Lambda 最后行值對對象進(jìn)行轉(zhuǎn)換、處理、非空安全操作處理可空對象、數(shù)據(jù)轉(zhuǎn)換、局部變量作用域also以 it 傳遞調(diào)用對象本身執(zhí)行副作用,比如日志、調(diào)試及額外操作記錄調(diào)試信息、檢查值后返回原對象apply以 this 傳遞調(diào)用對象本身對對象進(jìn)行初始化或配置構(gòu)建或設(shè)置對象屬性、初始化配置run以 this 傳遞Lambda 最后行值執(zhí)行代碼塊并返回計(jì)算結(jié)果對象上下文下的結(jié)果計(jì)算、封裝代碼塊with以 this 傳遞Lambda 最后行值同 run,但非擴(kuò)展函數(shù)調(diào)用組合操作同一對象,減少重復(fù)對象引用
參數(shù)區(qū)別
let 與 also 中,lambda 函數(shù)的參數(shù)默認(rèn)命名為 it,這樣在 lambda 內(nèi)部引用調(diào)用對象須寫成 it.someMethod() 或 it.propertyapply、run(擴(kuò)展版)和 with 中,lambda 內(nèi)部的 this 隱式代表調(diào)用對象,可以直接調(diào)用或讀取對象的屬性,而無需額外的參數(shù)前綴。注意:在 apply 中,由于是擴(kuò)展函數(shù),傳入的 lambda 表達(dá)式不會(huì)返回新值,而是始終返回調(diào)用對象本身;而 run 和 with 返回的是 lambda 表達(dá)式最后一行的結(jié)果。
使用場景比較
當(dāng)你需要對一個(gè)可能為 null 的對象進(jìn)行安全調(diào)用時(shí),let 是最佳選擇;如果你只是想在不改變對象的情況下監(jiān)控或記錄一些值,那么 also 很適合;當(dāng)你創(chuàng)建一個(gè)對象并需要在同一代碼塊中配置多個(gè)屬性時(shí),apply 極大地提升代碼可讀性,避免重復(fù)引用變量;如果你需要在對象上下文下計(jì)算某個(gè)表達(dá)式,并返回一個(gè)結(jié)果,run(擴(kuò)展版)會(huì)使代碼更為流暢;如果不想鏈?zhǔn)秸{(diào)用,但需要對一個(gè)對象執(zhí)行多個(gè)操作而最終返回一個(gè)值,with 是個(gè)不錯(cuò)的選擇。
第八部分:綜合示例與實(shí)際應(yīng)用
為了將上述擴(kuò)展函數(shù)的概念與使用場景更好地結(jié)合起來,我們將用一個(gè)復(fù)雜點(diǎn)的示例來綜合展示它們。假設(shè)我們正在構(gòu)建一個(gè)簡單的用戶注冊系統(tǒng),需要對用戶對象進(jìn)行配置、檢測與最終返回注冊信息。
我們通過以下完整的 Kotlin 文件展示如何采用各種擴(kuò)展函數(shù)來完成工作,并在每一步詳細(xì)注釋說明每種擴(kuò)展函數(shù)的作用和使用場景。
package com.example.registration
data class User(
var username: String = "",
var email: String = "",
var age: Int = 0,
var isActive: Boolean = false
)
fun main() {
// 使用 apply 進(jìn)行對象創(chuàng)建和初始化
val user = User().apply {
username = "john_doe"
email = "john@example.com"
age = 27
isActive = false
println("Inside apply: Initialized user with username = $username, email = $email, age = $age, isActive = $isActive")
}
// 使用 also 記錄用戶創(chuàng)建后的調(diào)試信息,不改變對象
user.also {
println("Logging user creation: $it")
}
// 使用 let 檢查 email 是否為空并轉(zhuǎn)換處理,返回處理結(jié)果
val emailStatus = user.email.let { emailStr ->
if (emailStr.isNotEmpty()) {
"Email is valid: $emailStr"
} else {
"Email is empty"
}
}
println("Result from let: $emailStatus")
// 使用 run 進(jìn)行用戶數(shù)據(jù)加工,返回格式化后的用戶描述信息
val userDescription = user.run {
// 進(jìn)行一些邏輯處理,比如把用戶名大寫
username = username.uppercase()
isActive = age >= 18
"User: $username, Email: $email, Age: $age, Active: $isActive"
}
println("Formatted user description from run: $userDescription")
// 使用 with 來對用戶對象進(jìn)行綜合操作,比如驗(yàn)證并拼接信息
val registrationSummary = with(user) {
println("Inside with block: Verifying user details...")
// 假設(shè)這里進(jìn)行一些復(fù)雜邏輯判斷
val status = if (isActive) "Active" else "Inactive"
"Registration Summary: Username = $username, Status = $status"
}
println("Summary from with: $registrationSummary")
}
在這個(gè)示例中,展示了每種擴(kuò)展函數(shù)的具體應(yīng)用:
使用 apply 完成對象的初始化和屬性設(shè)置,簡化重復(fù)引用。使用 also 記錄日志,但返回的是原始 user 對象,便于后續(xù)鏈?zhǔn)秸{(diào)用。使用 let 對對象的單一屬性(email)進(jìn)行檢查,并返回一個(gè)字符串描述。使用 run 在對象上下文中進(jìn)行邏輯處理,同時(shí)返回用戶描述信息。使用 with 封裝對 user 對象的綜合操作,并最后返回一個(gè)詳細(xì)的注冊摘要信息。
第九部分:深入討論各擴(kuò)展函數(shù)的優(yōu)缺點(diǎn)
9.1 let 的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
簡單易用。let 能夠讓你清晰地以非空狀態(tài)使用對象并返回處理后的結(jié)果。理想的鏈?zhǔn)秸{(diào)用工具,可以將計(jì)算結(jié)果傳遞給下一個(gè)函數(shù)??梢詫⒖煽諏ο蟀踩幚?、轉(zhuǎn)換和后續(xù)邏輯局限在一個(gè)閉包內(nèi)。
缺點(diǎn)
如果濫用 let(比如在不需要轉(zhuǎn)換的時(shí)候),可能會(huì)使代碼閱讀性變差,過多嵌套的 let 可能會(huì)難以理解。
9.2 also 的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
非常適合用于執(zhí)行副作用(如調(diào)試或記錄日志),使得代碼更加整潔。不會(huì)改變對象,始終返回調(diào)用對象本身,利于鏈?zhǔn)秸{(diào)用。
缺點(diǎn)
僅用于副作用操作,如果主要邏輯依賴返回的額外信息,則不能使用也不適用。
9.3 apply 的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
簡潔地對對象進(jìn)行初始化、設(shè)置屬性,使代碼整潔而直觀。代碼中可以直接引用對象成員,無需前綴,非常有利于對象構(gòu)造。
缺點(diǎn)
總是返回對象本身,不適用于需要其他返回值的場景。當(dāng)對象屬性較多或邏輯較復(fù)雜時(shí),apply 代碼塊可能會(huì)變得冗長。
9.4 run 的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
靈活,既可以使用對象上下文進(jìn)行計(jì)算,也可以作為非擴(kuò)展函數(shù)直接執(zhí)行代碼塊??捎糜诜庋b一段局部邏輯,并返回計(jì)算結(jié)果,適用于臨時(shí)變量邏輯封裝。
缺點(diǎn)
與 apply 相比,代碼塊內(nèi)不能直接修改返回值為對象本身,而是返回 lambda 最后一行的值,一定程度上局限了鏈?zhǔn)讲僮鳌?/p>
9.5 with 的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
非擴(kuò)展函數(shù)形式,使得函數(shù)調(diào)用更直觀,傳入對象后集中對對象的引用和操作。同樣適用于封裝對單個(gè)對象的多次操作,降低代碼重復(fù)調(diào)用對象名稱的復(fù)雜度。
缺點(diǎn)
與 run 無太大差異,但缺乏鏈?zhǔn)秸{(diào)用的流暢性,因?yàn)樗皇菙U(kuò)展函數(shù)。
第十部分:實(shí)戰(zhàn)案例解析
為使擴(kuò)展函數(shù)的用法更加貼近日常開發(fā),下面以一個(gè)實(shí)際的業(yè)務(wù)場景舉例,展示如何使用這些擴(kuò)展函數(shù)來編寫清晰而高效的代碼。假設(shè)我們需要編寫一個(gè)圖片處理模塊,功能包括:
將輸入圖片進(jìn)行非空判斷后轉(zhuǎn)換成灰度圖。在處理過程中記錄日志。對圖像對象進(jìn)行一系列配置。最后返回一份處理報(bào)告。
下面是詳細(xì)的代碼示例和解釋:
package com.example.imageprocessor
import java.awt.image.BufferedImage
import java.io.File
import javax.imageio.ImageIO
// 假設(shè)我們定義一個(gè)簡單的圖片處理函數(shù)
fun processImage(inputFile: File): String {
// 1. 使用 let 進(jìn)行非空判斷和轉(zhuǎn)換:加載圖片文件
val image: BufferedImage? = inputFile.let {
println("Attempting to load image from ${it.absolutePath}")
// 如果文件存在則加載圖片,否則返回 null
if (it.exists()) ImageIO.read(it) else null
}
// 2. 使用 also 在加載后記錄日志并檢查狀態(tài)
image?.also {
println("Image successfully loaded: width = ${it.width}, height = ${it.height}")
}
// 3. 使用 apply 對圖片對象進(jìn)行一系列配置(模仿配置操作)
val configuredImage = image?.apply {
// 模擬配置:例如調(diào)整圖像亮度,截取部分區(qū)域等
println("Applying configuration to the image")
// ... 這里實(shí)際會(huì)包含圖像處理邏輯
}
// 4. 使用 run 對處理結(jié)果作進(jìn)一步計(jì)算,返回處理報(bào)告
val report = configuredImage?.run {
println("Processing image to generate report")
// 返回處理后圖片的基本信息字符串
"Processed image: width = $width, height = $height"
} ?: "Image processing failed. Image is null."
// 5. 使用 with 封裝一段多操作邏輯,比如生成額外的報(bào)告內(nèi)容
val finalReport = with(inputFile) {
"File: ${name}, Size: ${length()} bytes. Report: $report"
}
return finalReport
}
fun main() {
val imageFile = File("sample.jpg")
val processingReport = processImage(imageFile)
println("Final Report:\n$processingReport")
}
在這個(gè)案例中:
使用 let 對傳入的 File 對象進(jìn)行處理,確保在讀取圖片前可以記錄日志及進(jìn)行簡單判斷。also 用來做額外的日志記錄,不影響后續(xù)鏈?zhǔn)秸{(diào)用。apply 用于模擬對圖片對象的配置處理,直接設(shè)定處理邏輯。run 用于計(jì)算處理結(jié)果,并返回最終數(shù)據(jù);with 則整合文件信息和處理報(bào)告,生成綜合性的最終報(bào)告。
通過這樣的實(shí)戰(zhàn)案例,我們可以看到擴(kuò)展函數(shù)如何協(xié)同工作,使得代碼邏輯清晰、結(jié)構(gòu)分明,同時(shí)減少了重復(fù)的代碼和冗長的引用操作。
第十一部分:總結(jié)與歸納
經(jīng)過前面詳細(xì)的講解,下面將各擴(kuò)展函數(shù)的核心要點(diǎn)進(jìn)行再次歸納:
基本概念
let:以 it 作為參數(shù),返回 lambda 最后一行值,適合數(shù)據(jù)轉(zhuǎn)換、局部判斷。also:以 it 作為參數(shù),返回調(diào)用對象本身,適合插入副作用操作。apply:以 this 作為lambda 接收者,直接操作對象屬性,返回對象本身,適合對象初始化。run:以 this 作為lambda 接收者,返回 lambda 的最后表達(dá)式結(jié)果,既能操作對象又能返回?cái)?shù)據(jù)。with:不是擴(kuò)展函數(shù),而是普通函數(shù),傳入對象后封裝操作,返回計(jì)算結(jié)果。 參數(shù)區(qū)別
let、also 需要通過 it 引用對象;apply、run(擴(kuò)展形式)和 with 則直接使用 this 進(jìn)行操作,可以省略 this 關(guān)鍵字,調(diào)用對象隱式作為 lambda 的接收者。 使用場景
針對可空對象的判斷做 let;記錄日志和打印調(diào)試信息使用 also;對象初始化和構(gòu)造使用 apply;對象內(nèi)操作計(jì)算返回特定數(shù)值使用 run;多次操作同一對象,并返回操作最終結(jié)果時(shí)使用 with。 實(shí)際應(yīng)用 在日常開發(fā)中,根據(jù)場景需求選擇合適的擴(kuò)展函數(shù),可以使代碼簡潔流暢,明確代碼執(zhí)行順序,減少冗余。同時(shí),這些擴(kuò)展函數(shù)可以一起使用,例如在一個(gè)業(yè)務(wù)流程中同時(shí)對對象進(jìn)行配置、檢查和結(jié)果返回。
總體來說,Kotlin 的擴(kuò)展函數(shù)是其語言設(shè)計(jì)中很強(qiáng)大的特性,通過理解每個(gè)擴(kuò)展函數(shù)的作用和區(qū)別,開發(fā)者可以編寫出更簡潔、可讀性更強(qiáng)的代碼。同時(shí),掌握這些擴(kuò)展函數(shù)也有助于更好地理解 Kotlin 的編程范式與最佳實(shí)踐。
柚子快報(bào)邀請碼778899分享:76.Kotlin擴(kuò)展函數(shù)簡介
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。