scala 类型问题:SoftReference、ReferenceQueues、SoftHashMap
编辑 到目前为止,大多数答案都集中在我错误地扩展了 Map 的事实。我已在示例代码中更正了这一点,但类型问题仍然存在,问题仍然存在。
我正在尝试在 Scala 中实现 SoftHashMap
,但遇到了类型不匹配的 问题错误:
inferred type arguments [K,V] do not conform to class SoftValue's type parameter bounds [K,+V <: AnyRef]
val sv = new SoftValue(kv._1, kv._2, queue)
我知道我过度限制了类型,但我不知道如何修复它。
import scala.collection.mutable.{Map, HashMap}
import scala.ref._
class SoftValue[K, +V <: AnyRef](val key:K, value:V, queue:ReferenceQueue[V]) extends SoftReference(value, queue)
class SoftMap[K, V] extends Map[K, V]
{
private val map = new HashMap[K, SoftValue[K, V]]
private val queue = new ReferenceQueue[V]
override def +=(kv: (K, V)):this.type =
{
val sv = new SoftValue(kv._1, kv._2, queue)
map(kv._1) = sv
this
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这样就可以编译了。 (编辑:我最初添加了
val value
,但这创建了一个强引用)。不确定您要如何处理迭代器...定义
SoftMap
时缺少V <: AnyRef
,因此 V 可以用作 SoftValue 构造函数的参数。This compiles. (edit: I initially added
val value
but that created a strong reference). Not sure how you want to handle iterator...You're missing
V <: AnyRef
when definingSoftMap
, so that V can be used as argument of theSoftValue
constructor.正如 Sam 指出的,第一个问题是您正在扩展 scala.collection.immutable.Map ,您通过别名 scala.Map 访问它。
其次,您已将
V
声明为协变类型参数。这意味着SoftMap[String, Dog]
是SoftMap[String, Any]
的子类型。在类定义中的逆变位置引用协变类型参数是无效的。类型安全的可变集合需要在同变和逆变位置引用元素类型:分别检索元素和添加元素。因此,它们必须将类型参数声明为不变的。
collection.mutable.Map
的定义表明了这一点:如果你扩展它,你会被告知:
另一方面:
Sam 也指出的最后一个问题是方法
+
不 做你想做的事情,至少从 Scala 2.8 开始。您应该实现 方法+=
。First problem, as pointed out by Sam, is that you are extending
scala.collection.immutable.Map
, which you are accessing through the aliasscala.Map
.Second, you have declared
V
as a covariant type parameter. This would mean that aSoftMap[String, Dog]
is a subtype ofSoftMap[String, Any]
. It is not valid to refer to the covariant type parameter in a contravariant position in the class definition.Typesafe mutable collections need to refer to the element type in both co- and contravariant positions: to retrieve elements and to add elements respectively. For this reason, they must declare the type parameter as invariant.
The definition of
collection.mutable.Map
shows this:If you extend this, you will be told:
On the other hand:
The final issue, also pointed out by Sam, is that the method
+
doesn't do what you intend, at least since Scala 2.8. You should implement the method+=
.如果
SoftMap
是可变的,那么您无法使用其值类型V
的超类型V1
来更新它。如果可能的话,旧映射将绑定到值为V1
类型的键值对,并且旧映射的类型为V
。在旧映射中查找新绑定时,这会导致类型错误。可变映射通过复制映射来实现
+
,不可变映射具有更高效的+
。另一方面,可变映射具有+=
,它会修改现有映射并且效率更高。+=
的参数是一个键和一个值,其中值不是映射值类型的超类型。在这种情况下,解决方案是复制地图。
编辑:
更改上述问题后收到的错误消息是由于软映射的类型参数
V
可以是任何类型,而类型V
SoftValue
的 code> 必须是AnyRef
的子类型(不能是Int
或Float
,即是AnyVal
的子类型)。因此,您无法从SoftMap
创建类型为V
的SoftValue
,因为有人可能会通过以下方式实例化SoftMap
:将V
设置为Int
。If
SoftMap
is going to be mutable, then you cannot update it with a supertypeV1
of it's value typeV
. If that were possible, the old map would have a binding to a key-value pair with a value of typeV1
, and the type of the old map isV
. This would result in type errors when looking up the new binding in the old map.Mutable maps implement
+
by copying the map, immutable maps have a more efficient+
. On the other hand, mutable maps have+=
which modifies the existing map and is more efficient. The argument of+=
is a key and a value, where a value isn't the supertype of the map value type.In this case, the solution is to copy the map.
EDIT:
The error message you've got after changing the question above is due to the fact that the type parameter
V
of the soft map can be any type whatsoever, while the typeV
of theSoftValue
has to be a subtype ofAnyRef
(cannot be anInt
or aFloat
, that is, a subtype ofAnyVal
). Therefore, you cannot create aSoftValue
with the typeV
from theSoftMap
, because someone might instantiate theSoftMap
by setting theV
to, sayInt
.