中級:擴展函數
在本章中,您將探索特殊的 Kotlin 函數,它們能讓您的程式碼更簡潔、更易讀。了解它們如何幫助您使用高效的設計模式,將您的專案提升到新的水平。
擴展函數
在軟體開發中,您經常需要在不更改原始程式碼的情況下修改程式的行為。例如,在您的專案中,您可能希望為來自第三方函式庫的類別添加額外功能。
擴展函數允許您為類別擴展額外功能。您呼叫擴展函數的方式與呼叫類別的成員函數相同,使用一個句點 .
。
在介紹擴展函數的完整語法之前,您需要了解接收者 (receiver) 是什麼。 接收者是函數被呼叫的對象。換句話說,接收者是資訊共享的目標。
在此範例中,main()
函數呼叫了 .first()
函數來回傳列表中第一個元素。 .first()
函數是針對 readOnlyShapes
變數呼叫的,因此 readOnlyShapes
變數是接收者。
要建立擴展函數,請撰寫您要擴展的類別名稱,後跟一個 .
和您的函數名稱。然後繼續撰寫函數宣告的其餘部分,包括其引數和回傳類型。
例如:
fun String.bold(): String = "<b>$this</b>"
fun main() {
// "hello" 是接收者
println("hello".bold())
// <b>hello</b>
}
在此範例中:
String
是被擴展的類別,也稱為接收者類型。bold
是擴展函數的名稱。.bold()
擴展函數的回傳類型是String
。"hello"
,一個String
的實例,是接收者物件。- 接收者在函數體內部透過 關鍵字:
this
來存取。 - 字串模板 (
$this
) 用來存取this
的值。 .bold()
擴展函數接收一個字串並將其包裝在<b>
HTML 元素中,以顯示粗體文字。
擴展導向設計
您可以將擴展函數定義在任何位置,這使您能夠建立擴展導向設計。這些設計將核心功能與有用但非必要的功能分開,使您的程式碼更易於閱讀和維護。
一個很好的例子是來自 Ktor 函式庫的 HttpClient
類別,它有助於執行網路請求。其核心功能是單一的 request()
函數,它接收 HTTP 請求所需的所有資訊:
class HttpClient {
fun request(method: String, url: String, headers: Map<String, String>): HttpResponse {
// 網路程式碼
}
}
在實踐中,最受歡迎的 HTTP 請求是 GET 或 POST 請求。對於函式庫來說,為這些常見用例提供較短的名稱是合理的。然而,這些不需要撰寫新的網路程式碼,只需要特定的 request
呼叫。換句話說,它們是定義為單獨的 .get()
和 .post()
擴展函數的完美候選者:
fun HttpClient.get(url: String): HttpResponse = request("GET", url, emptyMap())
fun HttpClient.post(url: String): HttpResponse = request("POST", url, emptyMap())
這些 .get()
和 .post()
函數會呼叫 request()
函數並帶有正確的 HTTP 方法,因此您不必這麼做。它們簡化了您的程式碼並使其更易於理解:
class HttpClient {
fun request(method: String, url: String, headers: Map<String, String>): HttpResponse {
println("Requesting $method to $url with headers: $headers")
return HttpResponse("Response from $url")
}
}
fun HttpClient.get(url: String): HttpResponse = request("GET", url, emptyMap())
fun main() {
val client = HttpClient()
// 直接使用 request() 進行 GET 請求
val getResponseWithMember = client.request("GET", "https://example.com", emptyMap())
// 使用 get() 擴展函數進行 GET 請求
val getResponseWithExtension = client.get("https://example.com")
}
這種擴展導向的方法在 Kotlin 的 標準函式庫 和其他函式庫中被廣泛使用。例如,String
類別有許多 擴展函數 可幫助您處理字串。
有關擴展函數的更多資訊,請參閱 擴展。
練習
練習 1
撰寫一個名為 isPositive
的擴展函數,它接收一個整數並檢查它是否為正數。
fun Int.// 在此撰寫您的程式碼
fun main() {
println(1.isPositive())
// true
}
範例解答
fun Int.isPositive(): Boolean = this > 0
fun main() {
println(1.isPositive())
// true
}
練習 2
撰寫一個名為 toLowercaseString
的擴展函數,它接收一個字串並回傳其小寫版本。
提示
String
類型的 .lowercase()
函數。 fun // 在此撰寫您的程式碼
fun main() {
println("Hello World!".toLowercaseString())
// hello world!
}
範例解答
fun String.toLowercaseString(): String = this.lowercase()
fun main() {
println("Hello World!".toLowercaseString())
// hello world!
}