假设有一个很好的理由我想要一个包含所有类型对象的通用HashMap。我还想将任何难看的instanceof
类型检查推送到数据结构中。为此,像getAs[T <: Any](key: String): Option[T]
这样的方法会很好。
class State extends HashMap[String, Any] {
override def +[T >: Any](elem: (String, T)): State = super.+(elem)
override def -(key: String): State = super.-(key)
def getAs[T](key: String): Option[T] = {
super.get(key) match {
case s: Some[T] => s
case _ => None
}
}
}
object State extends HashMap[String, Any] {
override def empty: State = super.empty
}
我还在包对象中定义了以下隐式转换:
implicit def fromHashMap(m: HashMap[String, Any]): State = m.asInstanceOf[State]
当我编译上面的代码时,我得到以下类型的擦除警告:
State.scala:10: warning: non variable type-argument T in type pattern Some[T] is
unchecked since it is eliminated by erasure
case s: Some[T] => s
^
这很不幸,因为该语句的整个目的是检查类型!
在这种情况下,除了采用实验性Manifest功能外,我还有其他选择吗?此外,有没有更好的基本方法来实现这一目标?
修改
我使用Manifest工作了。 Stackoverflow上的this article大大帮助了我。但是,我仍然很好奇是否有人可以推荐更清洁的方式。
Double Edit:
以下是此版本的当前版本。清单解决了我的直接问题。但是,我做的一个重大改变是使State类成为Map的包装器。这样做,我失去了继承的优点(即现在我必须明确地公开我需要的每个地图方法 a la keySet
。
class State(
map: HashMap[String, (Manifest[_], Any)] =
scala.collection.immutable.HashMap.empty[String, (Manifest[_], Any)]
) extends java.io.Serializable {
def +[T <: Any](elem: (String, T))(implicit m: Manifest[T]): State =
State(map.+((elem._1, (m, elem._2))))
def -(key: String): State = State(map.-(key))
def keySet = map.keySet
def getAs[T](key: String)(implicit m : Manifest[T]): Option[T] = {
map.get(key) match {
case Some((om: Manifest[_], o: Any)) =>
if (om <:< m) Some(o.asInstanceOf[T]) else None
case _ => None
}
}
}
object State {
def apply() = new State()
def apply(map: HashMap[String, (Manifest[_], Any)]) = new State(map)
def empty = State()
}
感谢所有到目前为止都看过这个的人。
使用State
和朋友here on GitHub查看ClassTag
的当前实施情况。我计划在TypeTag
可序列化时更新它以使用TypeCreator
。
答案 0 :(得分:2)
请注意,
时case s: Some[T]
因为Some
的类型参数被删除而不起作用,这是不同的:
case s @ Some(_: T)
在这种情况下,它不起作用,因为T
本身就是一个类型参数。虽然这对你的情况没有影响(不,除了清单之外别无选择),请考虑以下几点:
case s: Some[Int] // erased
case s @ Some(_: Int) // not erased