Scala 类[T]和#xA0的映射;不浇铸就浇铸

Scala 类[T]和#xA0的映射;不浇铸就浇铸,scala,Scala,我希望按照以下代码行将类标记映射到实例: trait Instances { def put[T](key: Class[T], value: T) def get[T](key: Class[T]): T } 这可以在不必解析get方法中的强制转换的情况下完成吗 更新: 对于更一般的情况,如何使用一些Foo[T]而不是Class[T]?您可以尝试从地图中检索对象作为Any,然后使用Class[T]进行“反射投射”: trait Instances {

我希望按照以下代码行将类标记映射到实例:

trait Instances {
  def put[T](key: Class[T], value: T)
  def get[T](key: Class[T]): T
}
这可以在不必解析get方法中的强制转换的情况下完成吗

更新:


对于更一般的情况,如何使用一些
Foo[T]
而不是
Class[T]

您可以尝试从地图中检索对象作为
Any
,然后使用
Class[T]
进行“反射投射”:

trait Instances {                                        
  private val map = collection.mutable.Map[Class[_], Any]()
  def put[T](key: Class[T], value: T) { map += (key -> value) }
  def get[T](key: Class[T]): T = key.cast(map(key))        
}

在我一个朋友的帮助下,我们将带有键的映射定义为Manifest,而不是Class,这样在调用时可以提供更好的api

我没有收到你关于“用一些Foo[T]代替Class[T]的一般情况”的最新问题。但这应该适用于您指定的情况

object Instances { private val map = collection.mutable.Map[Manifest[_], Any]() def put[T: Manifest](value: T) = map += manifest[T] -> value def get[T: Manifest]: T = map(manifest[T]).asInstanceOf[T] def main (args: Array[String] ) { put(1) put("2") println(get[Int]) println(get[String]) } } 对象实例{ private val map=collection.mutable.map[Manifest[\ux],Any]() def put[T:Manifest](值:T)=map+=Manifest[T]->value def get[T:Manifest]:T=map(Manifest[T]).asInstanceOf[T] def main(参数:数组[字符串]){ 付诸表决(1) 卖出(“2”) println(获取[Int]) println(获取[字符串]) } }
如果您想在不进行任何强制转换的情况下(即使在
get
)执行此操作,则需要编写一个异构映射。出于显而易见的原因,这很棘手。:-)最简单的方法可能是使用类似HList的结构并构建一个
查找
函数。但是,这并不简单,因为您需要为两个任意类型定义某种检查类型相等性的方法

我试图对元组和存在类型进行一些巧妙的处理。但是,Scala没有提供统一机制(模式匹配不起作用)。此外,子类型将整个事情联系在一起,基本上消除了它可能提供的任何类型的安全性:

val xs: List[(Class[A], A) forSome { type A }] = List(
  classOf[String] -> "foo", classOf[Int] -> 42)

val search = classOf[String]
val finalResult = xs collect { case (`search`, result) => result } headOption
在本例中,
finalResult
的类型为
Any
。这实际上是正确的,因为子类型意味着我们对
A
一无所知。这不是编译器选择该类型的原因,但它是一个正确的选择。例如:

val xs: List[(Class[A], A) forSome { type A }] = List(classOf[Boolean] -> 'bippy)
这是完全合法的!子类型表示在这种情况下,
A
将被选择为
Any
。这不是我们想要的,但你会得到的。因此,为了在不跟踪所有单个类型的情况下表达该约束(使用
HMap
),Scala需要能够表达一个约束,即一个类型是一个特定类型,而不是其他类型。不幸的是,Scala没有这种能力,因此我们基本上停留在通用约束方面

更新实际上,这是不合法的。刚试过,编译器就把它踢了出去。我认为这仅仅是因为
Class
的类型参数是不变的。因此,如果
Foo
是一个不变的确定类型,那么您应该不会遇到这种情况。它仍然不能解决统一问题,但至少它是合理的。不幸的是,类型构造器被假定在协变、反变和不变性之间处于一个神奇的超位置,因此如果它真的是一种任意类型
Foo
,那么你仍然陷在存在的前沿


总之:这应该是可能的,但前提是您将
实例
完全编码为
HMap
。就我个人而言,我只会在
get
中进行转换。简单多了

令人印象深刻的功能,将尽快重构一些代码:)谢谢Jean PhilipeYou不能避免在没有具体化类型的情况下施放,但这项技术对我来说非常安全。@michid确实,你不能避免施放。这里的
key.cast(obj)
实际上是一个选中的
(T)obj
cast。
cast
方法还将抛出一个
ClassCastException
,如果您给它的东西不是
T
的实例。