Kotlin MutableMap getter 和 setter 未按预期工作
Kotlin MutableMap getter and setter not working as expected
在 class 中,我有一个 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
}
}
但是当我 运行 代码时,像这样:
var sl = StringList()
sl.add("user=amo")
sl.values["user"] = "other"
val r = sl.values["user"]
我意识到 getter 执行了两次,setter 执行了两次 none。
我做错了什么?
几天前我用 List
而不是 MutableMap
回答了类似的问题,请参阅 here
这是 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) }
}
用法:
var values = MMap<String, String>(
getter = { println("get member $it") },
setter = { println("set member $it") }
)
发生这种情况是因为变量的 setter
在其 content
发生变化时不会被调用,但只有在存在赋值时才会被调用,而在您的情况下,您从未赋值过它。
var sl = StringList()
// Doesn't invoke the setter.
sl.add("user=amo")
// .values invokes the getter.
sl.values["user"] = "other"
// .values invokes the getter again.
val r = sl.values["user"]
// Invokes the setter since you made an assignment (this line is just an example on how to invoke the setter).
sl.values = mutableMapOf()
好的,我想我明白你想做什么。您希望在从 MutableMap 添加或检索值时发生一些副作用,对吗?
getter 和 属性 的 setter 与此无关。它们是 属性 的 getter 和 setter,对 MutableMap 的引用。它们不是地图本身中值的getter和setter。
您可以使用两种不同的策略来执行此操作:
1) 创建您自己的有副作用的地图 class。最简单的方法是通过 subclassing 一个现有的 MutableMap 实现,比如 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)
}
}
//...
}
2) 编写您自己的访问器,将调用传递给地图访问器并将您的副作用放在那里。这将迫使您调用这些特定函数,而不是直接从 class 外部访问地图,因此您可能希望将地图设为 属性 protected
或 private
.
open class StringList() {
private val list = mutableListOf<String>()
private val values = mutableMapOf<String, String>()
//...
fun putMapValue(key: String, value: String) {
println("Put key value pair $key / $value") // Side effect here
values[key] = value
}
fun getMapValue(key: String): String? {
println("Retrieved map value for key $key") // Side effect here
return values[key]
}
}
在 class 中,我有一个 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
}
}
但是当我 运行 代码时,像这样:
var sl = StringList()
sl.add("user=amo")
sl.values["user"] = "other"
val r = sl.values["user"]
我意识到 getter 执行了两次,setter 执行了两次 none。
我做错了什么?
几天前我用 List
而不是 MutableMap
回答了类似的问题,请参阅 here
这是 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) }
}
用法:
var values = MMap<String, String>(
getter = { println("get member $it") },
setter = { println("set member $it") }
)
发生这种情况是因为变量的 setter
在其 content
发生变化时不会被调用,但只有在存在赋值时才会被调用,而在您的情况下,您从未赋值过它。
var sl = StringList()
// Doesn't invoke the setter.
sl.add("user=amo")
// .values invokes the getter.
sl.values["user"] = "other"
// .values invokes the getter again.
val r = sl.values["user"]
// Invokes the setter since you made an assignment (this line is just an example on how to invoke the setter).
sl.values = mutableMapOf()
好的,我想我明白你想做什么。您希望在从 MutableMap 添加或检索值时发生一些副作用,对吗?
getter 和 属性 的 setter 与此无关。它们是 属性 的 getter 和 setter,对 MutableMap 的引用。它们不是地图本身中值的getter和setter。
您可以使用两种不同的策略来执行此操作:
1) 创建您自己的有副作用的地图 class。最简单的方法是通过 subclassing 一个现有的 MutableMap 实现,比如 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)
}
}
//...
}
2) 编写您自己的访问器,将调用传递给地图访问器并将您的副作用放在那里。这将迫使您调用这些特定函数,而不是直接从 class 外部访问地图,因此您可能希望将地图设为 属性 protected
或 private
.
open class StringList() {
private val list = mutableListOf<String>()
private val values = mutableMapOf<String, String>()
//...
fun putMapValue(key: String, value: String) {
println("Put key value pair $key / $value") // Side effect here
values[key] = value
}
fun getMapValue(key: String): String? {
println("Retrieved map value for key $key") // Side effect here
return values[key]
}
}