I have a following code:
class Mapped(var data:Map<String,String>){
val firstName:String by data
}
This works fine in case the Mapped
is used as follows:
val mapped = Mapped(mapOf("firstName" to "initialFirstName"))
println(mapped.firstName); // prints "initialFirstName"
However since the data
property is mutable we can change it's value i.e.:
mapped.data = mapOf("firstName" to "updated");
However the firstName
property still holds the "initialFirstName"
.
Is there a work around to this, known/documented albeit unexpected (to me) behavior?
Until the issues KT-5870, KT-9772 are resolved you can do the following:
operator fun <V, V1 : V> (() -> Map<in String, V>).getValue(thisRef: Any?, property: KProperty<*>): V1 {
val map = this()
return map[property.name] as V1
}
Which can then be used as follows:
class Mapped(var data:Map<String,String>){
val firstName:String by { data }
}
The above does not handle nullability well. Here's an improved version:
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")
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With