Kotlin MutableMap getter和setter未按预期工作

Kotlin MutableMap getter和setter未按预期工作,kotlin,operator-overloading,Kotlin,Operator Overloading,在一个类中,我有一个MutableMap,我想声明一个getter和一个setter,如下所示: open class StringList() { private val list= mutableListOf<String>() var values: MutableMap<String, String> get() { println("get member") // this is printe

在一个类中,我有一个
MutableMap
,我想声明一个getter和一个setter,如下所示:

open class StringList() {
    private val list= mutableListOf<String>()
    var values: MutableMap<String, String>
        get() {
            println("get member")        // this is printed.. twice
            return mutableMapOf<String, String>()
        }
        set(value) {
            println("set member")        // this is not printed
        }
     fun add(s: String, aObject: Any? = null): Int {
        list.add(s)
        return list.count() - 1
    }
}
我意识到执行是两次给getter,而不是setter


我做错了什么

几天前,我用
列表回答了一个类似的问题,而不是用
可变地图回答了一个类似的问题,请参见

这是带有
MutableMap

class MMap<T, U>(
        private val map: MutableMap<T, U> = mutableMapOf(),
        private val getter: ((T) -> Unit)? = null,
        private val setter: ((U) -> Unit)? = null
) : MutableMap<T, U> by map {

    override fun put(key: T, value: U): U? = 
        map.put(key, value).also { setter?.invoke(value) }

    override fun get(key: T): U? = 
         map[key].also { getter?.invoke(key) }
}
class-MMap(
私有val映射:MutableMap=mutableMapOf(),
private val getter:((T)->Unit)?=null,
专用val设置器:((U)->单位)?=null
):可变映射逐映射{
覆盖有趣的put(键:T,值:U):U?=
map.put(key,value).也是{setter?.invoke(value)}
覆盖乐趣获取(键:T):U?=
映射[key]。也是{getter?.invoke(key)}
}
用法:

var values = MMap<String, String>(
    getter = { println("get member $it") },
    setter = { println("set member $it") }
)
var值=MMap(
getter={println(“get member$it”)},
setter={println(“set成员$it”)}
)

几天前,我用
列表回答了一个类似的问题,而不是
可变地图
看到了吗

这是带有
MutableMap

class MMap<T, U>(
        private val map: MutableMap<T, U> = mutableMapOf(),
        private val getter: ((T) -> Unit)? = null,
        private val setter: ((U) -> Unit)? = null
) : MutableMap<T, U> by map {

    override fun put(key: T, value: U): U? = 
        map.put(key, value).also { setter?.invoke(value) }

    override fun get(key: T): U? = 
         map[key].also { getter?.invoke(key) }
}
class-MMap(
私有val映射:MutableMap=mutableMapOf(),
private val getter:((T)->Unit)?=null,
专用val设置器:((U)->单位)?=null
):可变映射逐映射{
覆盖有趣的put(键:T,值:U):U?=
map.put(key,value).也是{setter?.invoke(value)}
覆盖乐趣获取(键:T):U?=
映射[key]。也是{getter?.invoke(key)}
}
用法:

var values = MMap<String, String>(
    getter = { println("get member $it") },
    setter = { println("set member $it") }
)
var值=MMap(
getter={println(“get member$it”)},
setter={println(“set成员$it”)}
)

之所以发生这种情况,是因为变量的
setter
在其
内容发生更改时不会被调用,而只有在存在分配时才会被调用,而且在您的情况下,您从未分配过它

var sl=StringList()
//不调用setter。
sl.add(“用户=amo”)
//.values调用getter。
sl.values[“用户”]=“其他”
//.values再次调用getter。
val r=sl.values[“用户”]
//在进行赋值后调用setter(这一行只是关于如何调用setter的示例)。
sl.values=mutableMapOf()

之所以发生这种情况,是因为变量的
setter
在其
内容发生更改时不会被调用,而只有在存在分配时才会被调用,而且在您的情况下,您从未分配过它

var sl=StringList()
//不调用setter。
sl.add(“用户=amo”)
//.values调用getter。
sl.values[“用户”]=“其他”
//.values再次调用getter。
val r=sl.values[“用户”]
//在进行赋值后调用setter(这一行只是关于如何调用setter的示例)。
sl.values=mutableMapOf()

好的,我想我明白你想做什么。您希望在添加值或从可变映射检索值时发生一些副作用,对吗

属性的getter和setter与此无关。它们是属性的getter和setter,是对可变映射的引用。它们不是映射本身中值的获取者和设置者

您可以使用两种不同的策略来实现此目的:

1) 创建您自己的具有副作用的map类。实现这一点最简单的方法是通过对现有的可变映射实现(如HashMap)进行子类化

open class StringList() {
    private val list = mutableListOf<String>()
    val values = object: HashMap<String, String>(){
        override fun get(key: String): String? {
            println("Retrieved map value for key $key") // Side effect here
            return super.get(key)
        }

        override fun put(key: String, value: String): String? {
            println("Put key value pair $key / $value") // Side effect here
            return super.put(key, value)
        }
    }

    //...
}

好吧,我想我明白你想做什么。您希望在添加值或从可变映射检索值时发生一些副作用,对吗

属性的getter和setter与此无关。它们是属性的getter和setter,是对可变映射的引用。它们不是映射本身中值的获取者和设置者

您可以使用两种不同的策略来实现此目的:

1) 创建您自己的具有副作用的map类。实现这一点最简单的方法是通过对现有的可变映射实现(如HashMap)进行子类化

open class StringList() {
    private val list = mutableListOf<String>()
    val values = object: HashMap<String, String>(){
        override fun get(key: String): String? {
            println("Retrieved map value for key $key") // Side effect here
            return super.get(key)
        }

        override fun put(key: String, value: String): String? {
            println("Put key value pair $key / $value") // Side effect here
            return super.put(key, value)
        }
    }

    //...
}

也许我误解了,但你从来没有打电话给二传手,你打了两次电话给二传手。调用setter应该是s1.values=mutableMapOf etc,但是您两次引用s1.values作为getter,第一次是设置一个条目位而不是设置映射可能我误解了,但是您从来没有调用setter,您调用getter两次。调用setter将是s1.values=mutableMapOf etc,但您将s1.values作为getter引用了两次,第一次设置一个条目位时没有设置映射,因此不可能使用这种语法
sl.values[“user”]=“other”
来触发setter??否,我认为你对能手和二传手的工作有一个基本的误解。setter更改map
sl
的值。如果不向setter传递新值,则无法触发setter。在这种情况下,新值将是一个全新的可变映射。您的getter也存在根本性的缺陷,因为每次访问它时它都会返回一个全新的可变映射,所以一旦您修改它并稍后返回从中检索值,这些值就会消失。此语法转换为
sl.getValues().set(“user”,“other”)
。不,你不能让它调用
setValues()
。很好的解释@Tenfour04,让我回顾一下我的代码:)我现在看到了你的问题,Tenfour04和AlexeyRomanov都说了。所以不可能用这种语法
sl.values[“user”]=“other”
来触发setter??不,我认为你对能手和二传手的工作有一个基本的误解。setter更改map
sl
的值。如果不向setter传递新值,则无法触发setter。在这种情况下,新值将是一个全新的可变映射。您的getter也存在根本性的缺陷,因为每次访问它时它都返回一个全新的MutableMap,所以一旦您修改它并稍后返回从中检索值,这些值就会消失