财产代表团由可变地图烘焙

zet*_*tsu 6 kotlin

我有以下代码:

class Mapped(var data:Map<String,String>){
    val firstName:String by data
}
Run Code Online (Sandbox Code Playgroud)

如果Mapped使用如下,这工作正常:

val mapped = Mapped(mapOf("firstName" to "initialFirstName"))
println(mapped.firstName); // prints "initialFirstName"
Run Code Online (Sandbox Code Playgroud)

但是由于data属性是可变的,我们可以改变它的值,即:

mapped.data = mapOf("firstName" to "updated");
Run Code Online (Sandbox Code Playgroud)

不过,该firstName物业仍然拥有"initialFirstName".

有没有解决这个问题,已知/记录虽然意外(对我而言)行为?

mie*_*sol 6

在解决KT-5870,KT-9772问题之前,您可以执行以下操作:

operator fun <V, V1 : V> (() -> Map<in String, V>).getValue(thisRef: Any?, property: KProperty<*>): V1 {
    val map = this()
    return map[property.name] as V1
}
Run Code Online (Sandbox Code Playgroud)

然后可以使用如下:

class Mapped(var data:Map<String,String>){
    val firstName:String by { data }
}
Run Code Online (Sandbox Code Playgroud)

以上不能很好地处理可空性.这是一个改进版本:

operator fun <V, V1 : V> (() -> Map<in String, V>).getValue(thisRef: Any?, property: KProperty<*>): V1 {
    val map = this()
    val key = property.name
    @Suppress("UNCHECKED_CAST")
    val value = map[key] as V1
    if (property.returnType.isMarkedNullable) {
        return value
    } else {
        if(value != null){
            return value
        }
        if(map.containsKey(key)){
            throw KotlinNullPointerException("Property baking map returned null value for key '$key' for non nullable property: $property")
        } else {
            throw KotlinNullPointerException("Property baking map has no key '$key' for non nullable property $property")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)