原文地址: Kotlin學習快速入門(7)——擴展的妙用 - Stars-One的雜貨小窩 之前也模模糊糊地在用這個功能,也是十分方便,可以不用繼承,快速給某個類增加新的方法,本篇便是來講解下Kotlin中擴展這一概念的使用 說明 先解釋一下,擴展的說明,官方文檔上解釋: Kotlin 能夠擴展一個 ...
原文地址: Kotlin學習快速入門(7)——擴展的妙用 - Stars-One的雜貨小窩
之前也模模糊糊地在用這個功能,也是十分方便,可以不用繼承,快速給某個類增加新的方法,本篇便是來講解下Kotlin中擴展這一概念的使用
說明
先解釋一下,擴展的說明,官方文檔上解釋:
Kotlin 能夠擴展一個類的新功能,而無需繼承該類或者使用像裝飾者這樣的設計模式
簡單來說,就是可以不用繼承來讓一個類多出一個方法或屬性(成員變數),可能這樣說比較抽象,我們以一個簡單的例子來說
比如說,我們需要用到以下功能:
判斷String對象是否其是否為null或未空白字元串,如果為null或空白字元串,則返回true,否則返回false
此功能挺好實現,但我們想要實現此功能,無非就是3種方法:
- 寫個工具類StringUtil,然後傳遞有個String對象進去,方法返回
- 寫個新的類,讓其繼承於String類,之後再新增方法
- 用裝飾者模式,擴展類(這裡不多解釋裝飾者模式,可以自己百度查閱下資料)
但上面的方法,估計第一種各位都明白,也是十分簡單,但使用起來還是比較麻煩,還得將對象作為入參傳遞,如果使用Kotlin的擴展特性,還能變得更加簡單
而剩下兩種,改動均是較大,一般得看情況使用,也是不太推薦
擴展方法
我們以剛纔上述說的功能為例,實現判斷String對象是否其是否為null或未空白字元串,如果為null或空白字元串,則返回true,否則返回false
此功能
語法及使用
首先,顯示講解下語法
fun 類名.方法名(參數列表...):返回值{
}
看起來稍微有些抽象,我們直接上示例:
fun String.isBlankOrNullString(): Boolean {
return this == null || this.trim().length == 0
}
需要註意的是,方法里的this就是當前調用此方法的String對象
擴展方法使用:
fun main(args: Array<String>) {
val str = ""
println(str.isBlankOrNullString())
}
PS: 這裡的擴展方法寫在了頂層,是全局可用的
註意點
- 擴展方法會區分作用域(全局和局部)
- 類中存在於擴展方法同名同參數列表,相當於重載,此時以擴展方法為主
- 擴展方法可接收可空類型
擴展方法作用域
擴展方法的聲明位置,會決定此擴展方法的作用域
如下麵示例:
fun main() {
val str = ""
println(str.isBlankOrNullString())
}
class User {
val str = ""
}
fun String.isBlankOrNullString(): Boolean {
return this == null || this.trim().length == 0
}
我們將方法寫在了最外層(即與class關鍵字同級),此時,我們可以在任意的類中調用此方法
但如果我們稍微改一下,如下:
fun main() {
val str = ""
//這裡會報錯!!
//println(str.isBlankOrNullString())
}
class User {
val str = ""
fun sayHello() {
//類中可以正常使用
str.isBlankOrNullString()
}
fun String.isBlankOrNullString(): Boolean {
return this == null || this.trim().length == 0
}
}
擴展方法重載問題
由於是聲明方法,可能會出現方法名重名的情況,即我們Java基礎中說到的重載關係
這裡,如果出現了重載的情況(方法名和參數列表相同),會以類中的方法為主(即會忽略掉擴展方法)
上面此句,是根據文檔上總結得來的,實際上也是測試通過
fun main() {
Example().printFunctionType()
}
class Example {
fun printFunctionType() { println("Class method") }
}
fun Example.printFunctionType() { println("Extension function") }
最後輸出的是Class method
但這裡有個奇怪的情況,我以String的擴展為例,測試發現與上述結論不一致!!
以下是我的測試代碼:
fun main() {
val str = ""
println(str.isNullOrBlank())
}
fun String.isNullOrBlank(): Boolean {
println("進入我們的方法里")
return this == null || this.trim().length == 0
}
最終輸出:
進入我們的方法里
true
看著列印,這明顯就是進到我們定義的擴展方法里啊