擴展方法
Kotlin支持擴展方法,擴展方法是個很有意思的東西
還是舉個栗子比較直觀
比如我們想打印10次“abc”的字符串,最容想到的是使用循環。那麼單獨抽出來成方法,就是這樣
fun String.copyContent(times: Int): String{
var string = StringBuilder()
for (i in 0 until times){
string.append(this)
}
return string.toString()
}
你仔細看看這個方法,它和普通方法有一點不太一樣,那就是它的方法名前有一個 String.
這麼寫有什麼好處呢?看下面的調用操作你就明白了
println( "abc".copyContent(10))
上面的結果就是輸出10次abc的字符串
有沒有發現很簡潔,直接字符串點方法就ok了
通過上面方式定義的方法就是擴展方法,注意擴展方法的this代替的就是調用者“abc”
其實上面的栗子還可以寫的更騷
怎麼個騷操作呢,那就是使用運算符
operator fun String.times(times: Int): String{
var string = StringBuilder()
for (i in 0 until times){
string.append(this)
}
return string.toString()
}
下面就是見證奇蹟的時候了
println("abc"*10)
不知道的一看會以爲String類有這麼一種運算呢,啊哈哈,可以說這波操作很騷了
屬性代理
屬性代理是什麼,代理模式?
我們先看一個栗子:
Kotlin對常量進行延遲加載對時候就用到了屬性代理,它是這樣的:
val lazyValue: String by lazy {
println("computed!")
"Hello"
}
fun main() {
println(lazyValue)
println(lazyValue)
}
輸出結果
computed!
Hello
Hello
可以看到computed!只輸出了一次,這表明它的確是在用到這個常量的時候纔去賦值。
該說回屬性代理了,其實它的內部就是通過lazy這個屬性代理實現的
但是它怎麼通過屬性代理實現延遲加載的呢?這裏不說,因爲不是重點,也不是我舉這個栗子的目的,筆者是想讓你們感受到屬性代理的強大之處,它把所有的具體實現都交給了某個屬性來做,對外部來說是透明的,這就非常舒服了。
下面說說我們怎麼去實現屬性代理?
還是舉個栗子:
實現通過屬性代理的方式對變量進行賦值和取值的操作(栗子很簡單,關鍵看實現)
屬性代理類Delegate
class Delegate{
private var value: String ?= null
operator fun getValue(thisRef: Any?, property: KProperty<*>): String{
println("$thisRef, thank you for delegating '${property.name}' to me!")
return value?: ""
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
this.value = value
println("$value has been assigned to '${property.name}' in $thisRef.")
}
}
可以看到代理類有兩個方法,setValue()和getValue()
注意:如果是常量val的話,只需要實現getValue就可以;如果是變量var,那就需要實現setValue()和getValue()兩個方法
通過屬性代理實現功能
var de = Delegate()
var b: String by de
b = "10"
println(b)
輸出結果
10 has been assigned to 'b' in null.
null, thank you for delegating 'b' to me!
10
根據輸出結果可以看到整個過程是通過屬性代理類Delegate實現的
這個栗子雖然簡單,但透過表面看本質,我們只需要通過一個屬性就可以實現功能,至於怎麼實現的對我們來說是透明的。