myaa
05/28/2020, 6:20 PMclass Test(
first: String = "default",
second: Int = 42,
third: Boolean = false
) {
val map = mutableMapOf<String, Any>()
inner class MyDelegate(private val default: Any) {
operator fun getValue(receiver: Test, property: KProperty<*>) =
map.computeIfAbsent(property.name) { default }
operator fun setValue(receiver: Test, property: KProperty<*>, value: Any) {
map[property.name] = value
}
}
var first by MyDelegate(first)
var second by MyDelegate(second)
var third by MyDelegate(third)
}
val t = Test(second = 100)
t.first = "test"
println(t.map) // {first=test} - WRONG
println("${t.first} ${t.second} ${t.third}") // test 100 false
but i don't like the redundant definitions (having to declare each field as an argument as well), and this example also behaves incorrectly in that the map doesn't get populated with all the arguments immediately upon instantiationStefan Beyer
05/28/2020, 6:32 PMmyaa
05/28/2020, 6:34 PMStefan Beyer
05/28/2020, 6:34 PMmyaa
05/28/2020, 6:36 PMStefan Beyer
05/28/2020, 6:43 PMketurn
05/28/2020, 6:43 PMStefan Beyer
05/28/2020, 6:44 PMmyaa
05/28/2020, 6:46 PMMap
interface? and then implement the get
and put
methods using reflectionStefan Beyer
05/28/2020, 6:54 PMmyaa
05/28/2020, 6:58 PMMatteo Mirk
05/28/2020, 7:03 PMclass Test private constructor(val map: MutableMap<String, Any?>) {
var first by map
var second by map
var third by map
companion object {
operator fun invoke(
first: String = "default",
second: Int = 42,
third: Boolean = false
) = Test(mutableMapOf(
"first" to first,
"second" to second,
"third" to third
))
}
}
Stefan Beyer
05/28/2020, 7:13 PMimport kotlin.reflect.KProperty
import kotlin.reflect.full.declaredMemberProperties
class Test(
first: String = "default",
second: Int = 42,
third: Boolean = false
) {
val map: MutableMap<String, Any?> by lazy {
this::class
.declaredMemberProperties
.filter { it.name != "map" }
.associate { it.name to it.getter.call(this) }
.toMutableMap()
}
inner class MyDelegate<T>(private var currentValue: T) {
operator fun getValue(receiver: Test, property: KProperty<*>): T = currentValue
operator fun setValue(receiver: Test, property: KProperty<*>, value: T) {
currentValue = value
receiver.map[property.name] = value
}
}
var first by MyDelegate(first)
var second by MyDelegate(second)
var third by MyDelegate(third)
}
val t = Test(second = 100)
t.first = "test"
println(t.map) // {first=test, second=100, third=false}
println("${t.first} ${t.second} ${t.third}") // test 100 false
myaa
05/28/2020, 8:19 PM