Scala如何为map编写get(name:String,type:Class)

时间:2014-08-25 17:19:16

标签: scala

我希望能够有[String,Any]类型的地图实现,其中我可以存储不同类的对象,然后我希望能够做到

import app.User;
....
usr = map.getAs("user",User)// with usr being an object of Class/Object User. If user is not of that type it throws an exception.

用户之前已存储在地图中。

这可能吗?

我甚至可以是一个独立的方法,例如

 usr = getAs(map,"user",User)

由于

3 个答案:

答案 0 :(得分:5)

您可以使用ClassTag。我没有很多经验,但这样的事情应该有效:

def getAs[T: ClassTag](m: Map[String, Any], key: String): T = 
  m(key).asInstanceOf[T]

用法:

val map = Map[String, Any]("one" -> 1, "hello"-> "world")
getAs[String](map, "hello")
res1: String = world

我让你处理异常,你可以简单地将asInstanceOf包裹在Try或者你喜欢的策略中。我还建议将返回类型更改为Option[T]

答案 1 :(得分:1)

谢谢vptheron。这绝对有效。 我接受了你的建议并使用Option [T]并使用了匹配。

def getAsOption[T: ClassTag](m: Map[String, Any], key: String): Option[T] =
m.get(key) match {
    case x : Option[T] => x
    case _ => None
}   

我想要一种在play框架中传递随机内容的机制,虽然纯粹主义者不喜欢它,但对我来说这似乎是一个很好的解决方案。

答案 2 :(得分:1)

我认为使用TypeTag会做得更好,除非你永远不会将值转换为泛型类型。

import scala.reflect.runtime.universe._

trait Typed[A] {
  val value: A
  implicit val ttag: TypeTag[A]
}

def cast[A, B: TypeTag](v: Typed[A]): Option[B] = {
  val tA = typeOf[A](v.ttag)
  val tB = typeOf[B]
  def vB = v.value.asInstanceOf[B]
  if (tA <:< tB) Some(vB) else None
}

def getTyped[A, B, C: TypeTag](map: Map[A, Typed[B]], key: A): Option[C] = {
  map get key flatMap cast[B, C]
}