Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
掌握Kotlin代表的窍门_Kotlin_Delegates_Delegation - Fatal编程技术网

掌握Kotlin代表的窍门

掌握Kotlin代表的窍门,kotlin,delegates,delegation,Kotlin,Delegates,Delegation,我正努力把我的头缠在科特林代表身上。我发现它与泛型一起使用时特别棘手。在我的例子中,我需要一个可以存储任意类型值的委托。第一次访问委托属性时,它返回存储的值。所有后续访问只返回null。如果我再次设置该值,则下一次访问将返回该值,并且所有后续访问操作将再次返回null。它的工作原理如下: val a: Int by AccessOnce() // or String, or Boolean, or whatever println(a) // null a = 42 println(a) //

我正努力把我的头缠在科特林代表身上。我发现它与泛型一起使用时特别棘手。在我的例子中,我需要一个可以存储任意类型值的委托。第一次访问委托属性时,它返回存储的值。所有后续访问只返回
null
。如果我再次设置该值,则下一次访问将返回该值,并且所有后续访问操作将再次返回
null
。它的工作原理如下:

val a: Int by AccessOnce() // or String, or Boolean, or whatever
println(a) // null
a = 42
println(a) // 42
println(a) // null

a = 100
println(a) // 100
println(a) // null
这是到目前为止我所拥有的代码,但它对
getValue
setValue
签名不满意。你能帮我吗

import kotlin.reflect.KProperty

class AccessOnce <T> {
    var storedValue: T? = null
    operator fun getValue(thisRef: T?, property: KProperty<*>): T? {
        val retVal =  storedValue
        storedValue = null
        return retVal
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
        storedValue = value
    }

}
导入kotlin.reflect.KProperty
类访问一次{
var存储值:T?=null
运算符fun getValue(thisRef:T?,属性:KProperty):T{
val retVal=存储值
storedValue=null
返回返回
}
运算符fun setValue(thisRef:Any?,属性:KProperty,值:T?){
storedValue=value
}
}

您的代码的问题是您将
thisRef
的类型与属性本身的类型混为一谈
thisRef
是具有被委托属性的任何对象。在大多数情况下,您只需将其设置为类型
Any
,这样您的委托就可以在您喜欢的任何类中使用。但是,如果您有一种特殊类型的委托,它只适用于特定类型的类,您可以将该类型用于
thisRef
,然后在运算符函数中,您可以让getter和/或setter调用该类上的其他函数或执行其他工作

因此,要修复您的问题,只需将
thisRef
更改为
Any

class AccessOnce <T> {
    var storedValue: T? = null
    operator fun getValue(thisRef: Any, property: KProperty<*>): T? {
        val retVal =  storedValue
        storedValue = null
        return retVal
    }

    operator fun setValue(thisRef: Any, property: KProperty<*>, value: T?) {
        storedValue = value
    }

}

您可以实现接口以确保您的委托对象具有正确的签名。好吧,很酷,但我对
R-拥有委托属性的对象类型感到困惑。这意味着什么?
ReadWriteProperty
是一个接口,所以在
getValue
function
中,这个
是(在您的例子中)AccessOnce类。但是您可以在others类中使用AccessOnce()的
val a:Int
R
必须是拥有
a
的对象的类型(或超类型)。
    operator fun getValue(thisRef: Any, property: KProperty<*>): T? =
         storedValue.also { storedValue = null }