如何在不丢失类型的情况下代理对哈希图的调用 [英] How to proxy a call to a hashmap without losing the type
问题描述
在下面的代码中,当我直接从哈希图中获取属性时,我得到了正确的属性类型 (PropertyA
).
In the code below I get the correct type of the property (PropertyA
) when I get it straight from the hashmap.
当我通过 ClassAbstract
中的 get 方法代理此调用时,类型为 PropertyAbstract[_ <: A]
When I proxy this call through the get method in ClassAbstract
the type is PropertyAbstract[_ <: A]
有没有办法代理对 hashmap 的调用并保持正确的类型?
Is there a way to proxy the call to the hashmap and keep the correct type?
另一个问题是如何通过类型检查将对象添加到 revs
数组?
Another question is how can I add objects to the revs
array with type checking?
class A
class B extends A
class C extends A
abstract class PropertyAbstract[T] {
val revs = new java.util.ArrayList[T]
}
class PropertyA extends PropertyAbstract[B]
class PropertyB extends PropertyAbstract[C]
abstract class ClassAbstract {
val props: scala.collection.immutable.HashMap[String, PropertyAbstract[_ <: A]]
def get(prop: String) = props.get(prop).get
}
class Class extends ClassAbstract {
val props = collection.immutable.HashMap(
"prop1" -> new PropertyA,
"prop2" -> new PropertyB
)
}
object Test extends App {
val the_class = new Class
val proxied_prop = the_class.get("prop1")
val direct_prop = the_class.props.get("prop1").get
// wont compile (found: B required: _$1 <: A)
proxied_prop.revs.add(new B)
// wont compile (found: B required: C with B)
direct_prop.revs.add(new B)
}
想要的结果是我可以将 B
类型的元素添加到 prop1,但不能添加 C
The wanted result is that I could add an element of type B
to prop1, but not an element of type C
推荐答案
看来您想要的本质上是一个类型化的地图.很明显,您尝试做的事情根本行不通.当您调用 get
时,您会收到一个未知 X
的 PropertyAbstract[X]
(除了它是 A
).那么你怎么能假设它需要 B
秒?
It seems that what you want is essentially a typed map. It's pretty obvious that what you are trying to do simply cannot work. When you call get
, you receive a PropertyAbstract[X]
for an unknown X
(except in that it is a subtype of A
). How can you then assume it takes B
s?
解决方案是让您的 PropertyAbstract
逆变 但这意味着它不能以任何合理的方式成为可变集合(它可以当然是可变的,但你能得到的是 A
).
The solution is for your PropertyAbstract
to be contravariant but this means that it cannot be a mutable collection in any sensible manner (it can be mutable of course, but what you can get out would be an A
).
scala> class A; class B extends A; class C extends A
defined class A
defined class B
defined class C
scala> abstract class PropertyAbstract[-T] { val revs = new java.util.ArrayList[AnyRef] }
defined class PropertyAbstract
scala> class PropertyA extends PropertyAbstract[B]; class PropertyB extends PropertyAbstract[C]
defined class PropertyA
defined class PropertyB
scala> abstract class ClassAbstract {
| val props: Map[String, PropertyAbstract[_ <: A]]
| def get(prop: String) = (props get prop).get
| }
defined class ClassAbstract
scala> class Class extends ClassAbstract { val props = Map("prop1" -> new PropertyA, "prop2" -> new PropertyB) }
defined class Class
scala> val the_class = new Class
the_class: Class = Class@298508
scala> val proxied_prop = the_class.get("prop1")
proxied_prop: PropertyAbstract[_ <: A] = PropertyA@a269e2
scala> val direct_prop = the_class.props.get("prop1").get
direct_prop: PropertyAbstract[C with B] = PropertyA@a269e2
以下编译:
scala> proxied_prop.revs.add(new B)
res0: Boolean = true
scala> direct_prop.revs.add(new B)
res1: Boolean = true
当然你可以在里面放任何东西!
But of course you could put anything in there!
也许你应该看看 Miles Sabin 的无形你可以在异构类型集合方面做的事情.
Perhaps you should take a look at Miles Sabin's shapeless for the sort of stuff you can do in terms of heterogeneously-typed collections.
这篇关于如何在不丢失类型的情况下代理对哈希图的调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!