kotlin-委託和屬性委託

前言

委託模式已經證明是實現繼承的一個很好的替代方式, 而 Kotlin 可以零樣板代碼地原生支持它,接下來讓我們試試

委託

在kotlin中使用的是by關鍵字實現委託,下邊的這段代碼是kotlin官網的代碼

interface Base {
    fun print()
}

class BaseImpl(val x: Int) : Base {
    override fun print() { print(x) }
}

class Derived(b: Base) : Base by b

fun main() {
    val b = BaseImpl(10)
    Derived(b).print()
}

在我的理解便是通過by關鍵在標識了b便意味着吧b對象存儲在Derived類中,並且編譯器會將b的所有的方法轉發給Derived對象

覆蓋由委託實現的接口成員

覆蓋符合預期:編譯器會使用 override 覆蓋的實現而不是委託對象中的。如果將 override fun printMessage() { print(“abc”) } 添加到 Derived,那麼當調用 printMessage 時程序會輸出“abc”而不是“10”:

interface Base {
    fun printMessage()
    fun printMessageLine()
}

class BaseImpl(val x: Int) : Base {
    override fun printMessage() { print(x) }
    override fun printMessageLine() { println(x) }
}

class Derived(b: Base) : Base by b {
    override fun printMessage() { print("abc") }
}

fun main() {
    val b = BaseImpl(10)
    Derived(b).printMessage()
    Derived(b).printMessageLine()
}

但請注意,以這種方式重寫的成員不會在委託對象的成員中調用 ,委託對象的成員只能訪問其自身對接口成員實現:

委託屬性

有一些常見的屬性類型,雖然我們可以在每次需要的時候手動實現它們, 但是如果能夠爲大家把他們只實現一次並放入一個庫會更好。例如包括

延遲屬性(lazy properties): 其值只在首次訪問時計算;
lazy() 是接受一個 lambda 並返回一個 Lazy 實例的函數,返回的實例可以作爲實現延遲屬性的委託: 第一次調用 get() 會執行已傳遞給 lazy() 的 lambda 表達式並記錄結果, 後續調用 get() 只是返回記錄的結果。

val lazyValue :String by lazy {
    println("computed!")
    "Hello"
}
fun main() {
  
    println(lazyValue)
    println(lazyValue)
}

可觀察屬性(observable properties): 監聽器會收到有關此屬性變更的通知;

Delegates.observable() 接受兩個參數:初始值與修改時處理程序(handler)。 每當我們給屬性賦值時會調用該處理程序(在賦值後執行)。它有三個參數:被賦值的屬性、舊值與新值:

import kotlin.properties.Delegates

class User {
    var name: String by Delegates.observable("<no name>") {
        prop, old, new ->
        println("$old -> $new")
    }
}

fun main() {
    val user = User()
    user.name = "first"
    user.name = "second"
}

把屬性儲存在映射中

一個常見的用例是在一個映射(map)裏存儲屬性的值。 這經常出現在像解析 JSON 或者做其他“動態”事情的應用中。 在這種情況下,你可以使用映射實例自身作爲委託來實現委託屬性。

class User(val map: Map<String, Any?>) {
    val name: String by map
    val age: Int     by map
}

val user = User(mapOf(
    "name" to "John Doe",
    "age"  to 25
))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章