美文网首页
[学习]拥抱kotlin(六)

[学习]拥抱kotlin(六)

作者: 吴敬悦 | 来源:发表于2021-02-10 23:43 被阅读0次

    今天看委托模式。
    有一篇讲得不错的: 一文彻底搞懂Kotlin中的委托
    还有中文官网的教程: 委托属性
    还有一篇官方的教程: Kotlin Vocabulary | Kotlin 委托代理

    刚开始是不知道这是啥的,像下面的代码:

    private val viewmodel: LiveDataViewModel by viewModels { LiveDataVMFactory }
    

    我最看不懂的就是 by ,一头雾水,不知道这里是啥含义,于是便开启了我的学习之旅。
    看语法形式:

    val/var <属性名>: <类型> by <表达式>
    

    在 by 后面的表达式是该 委托, 因为属性对应的 get()(与 set())会被委托给它的 getValue() 与 setValue() 方法。 属性的委托不必实现任何的接口,但是需要提供一个 getValue() 函数(与 setValue()——对于 var 属性)。

    看例子:

    import kotlin.reflect.KProperty
    
    class Delegate {
        operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
            return "$thisRef, thank you for delegating '${property.name}' to me!"
        }
    
        operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
            println("$value has been assigned to '${property.name}' in $thisRef.")
        }
    }
    class Test {
        var name: String by Delegate()
    }
    fun main(args: Array<String>) {
        val test = Test()
        test.name = "100"
        println(test.name)
    }
    // 输出:
    // 100 has been assigned to 'name' in Test@72ea2f77.
    // Test@72ea2f77, thank you for delegating 'name' to me!
    

    可以看到要想委托需要实现对应的方法 getValuesetValue 。其中的参数要求:

    • thisRef —— 必须与属性所有者类型(对于扩展属性——指被扩展的类型)相同或者是其超类型。
    • property —— 必须是类型 KProperty<*> 或其超类型。
    • value — 必须与属性类型相同(或者是其超类型)。

    其中 thisRef 指的是类,在上面的例子中我编写的是 Any ,所以不受限制,如果我写的是 Int ,那么这里就会失败:

    当thisRef不正确时会出现错误
    可以看出这里需要的是 TestTest 的超类,当然可以直接写 Any 。既然超类是可以的,那么下面也是可行的:
    class Delegate {
        operator fun getValue(thisRef: SupperTest?, property: KProperty<*>): String {
            return "$thisRef, thank you for delegating '${property.name}' to me!"
        }
    
        operator fun setValue(thisRef: SupperTest?, property: KProperty<*>, value: String) {
            println("$value has been assigned to '${property.name}' in $thisRef.")
        }
    }
    open class SupperTest
    class Test: SupperTest() {
        var name: String by Delegate()
    }
    

    相关文章

      网友评论

          本文标题:[学习]拥抱kotlin(六)

          本文链接:https://www.haomeiwen.com/subject/sdoxxltx.html