如何在不丢失类型的情况下代理对哈希图的调用 [英] How to proxy a call to a hashmap without losing the type

查看:23
本文介绍了如何在不丢失类型的情况下代理对哈希图的调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的代码中,当我直接从哈希图中获取属性时,我得到了正确的属性类型 (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 时,您会收到一个未知 XPropertyAbstract[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 Bs?

解决方案是让您的 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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆