中級:擴充函數
在本章中,您將探索特殊的 Kotlin 函數,這些函數能讓您的程式碼更加簡潔易讀。了解它們如何幫助您使用高效的設計模式,將您的專案提升到新的水平。
擴充函數
在軟體開發中,您經常需要修改程式的行為,而無需更改原始程式碼。例如,在您的專案中,您可能希望為第三方函式庫 (third-party library) 中的類別添加額外的功能。
擴充函數 (Extension functions) 允許您為類別擴展額外的功能。您呼叫擴充函數的方式,與呼叫類別的成員函數 (member functions) 相同。
在介紹擴充函數的語法之前,您需要了解 接收者型別 (receiver type) 和 接收者物件 (receiver object) 這兩個術語。
接收者物件是函數被呼叫的對象。換句話說,接收者是資訊被共享的地方或對象。
在此範例中,main()
函數呼叫了 .first()
函數。.first()
函數是在 readOnlyShapes
變數上呼叫的,因此 readOnlyShapes
變數就是接收者。
接收者物件具有一個型別 (type),以便編譯器 (compiler) 了解何時可以使用該函數。
此範例使用標準函式庫 (standard library) 中的 .first()
函數來返回列表中的第一個元素。要創建您自己的擴充函數,請寫下您想要擴展的類別名稱,後跟一個 .
和您的函數名稱。然後繼續完成函數宣告的其餘部分,包括其參數和返回型別。
例如:
fun String.bold(): String = "<b>$this</b>"
fun main() {
// "hello" is the receiver object
println("hello".bold())
// <b>hello</b>
}
在此範例中:
String
是被擴展的類別,也稱為接收者型別。bold
是擴充函數的名稱。.bold()
擴充函數的返回型別是String
。"hello"
,一個String
的實例,是接收者物件。- 接收者物件在函數體內部透過 關鍵字 (keyword):
this
存取。 - 程式碼中的字串模板 (string template) 用於存取
this
的值。 .bold()
擴充函數接受一個字串,並將其以用於粗體文字的<b>
HTML 元素返回。
擴充導向設計
您可以在任何地方定義擴充函數,這使您能夠創建擴充導向的設計。這些設計將核心功能與有用但不必要的特性分開,使您的程式碼更易於閱讀和維護。
一個很好的例子是 Ktor 函式庫中的 HttpClient
類別,它有助於執行網路請求 (network requests)。其核心功能是一個單一的 request()
函數,它接受 HTTP 請求所需的所有資訊:
class HttpClient {
fun request(method: String, url: String, headers: Map<String, String>): HttpResponse {
// Network code
}
}
實際上,最常見的 HTTP 請求是 GET 或 POST 請求。函式庫為這些常見使用案例提供較短的名稱是合理的。然而,這些請求不需要編寫新的網路程式碼,只需特定的請求呼叫即可。換句話說,它們是定義為獨立的 .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()
// Making a GET request using request() directly
val getResponseWithMember = client.request("GET", "https://example.com", emptyMap())
// Making a GET request using the get() extension function
val getResponseWithExtension = client.get("https://example.com")
}
這種擴充導向的方法廣泛應用於 Kotlin 的 標準函式庫 (standard library) 和其他函式庫中。例如,String
類別有許多 擴充函數 來幫助您處理字串。
有關擴充函數的更多資訊,請參閱 擴展 (Extensions)。
練習
練習 1
編寫一個名為 isPositive
的擴充函數,它接受一個整數並檢查它是否為正數。
|---|---|
fun Int.// Write your code here
fun main() {
println(1.isPositive())
// true
}
|---|---|
fun Int.isPositive(): Boolean = this > 0
fun main() {
println(1.isPositive())
// true
}
練習 2
編寫一個名為 toLowercaseString
的擴充函數,它接受一個字串並返回其小寫版本。
提示
使用針對 String
型別的 .lowercase()
函數。
|---|---|
fun // Write your code here
fun main() {
println("Hello World!".toLowercaseString())
// hello world!
}
|---|---|
fun String.toLowercaseString(): String = this.lowercase()
fun main() {
println("Hello World!".toLowercaseString())
// hello world!
}