Scala 反射

6

我想创建一个哈希映射来存储参数名及其值,但这些参数具有不同的类型。我可以使用HashMap[String, Any],但是我之后就无法知道它们的类型了。有没有办法恢复类型信息?或者有更好的方法来存储键值对?


这些答案中是否有任何帮助到您的?如果没有,您是否有任何反馈可以帮助我们更好地满足您的需求? - Aaron Novstrup
好吧,它们中没有一个真正解决了我的问题。有些人(线下)告诉我没有优雅的解决方案。后来我改变了我的设计以避免这样的问题... - user398384
使用Daniel的解决方案,将get更改为返回键值和值的清单对怎么样? - Jean-Philippe Pellet
3个回答

5

您是想要访问静态类型信息还是动态类型信息?如果您需要前者,可以使用类型化键。以下是一些示例代码:

final class Key[T]

object Registry {
   private var backingMap: Map[Key[_], _] = Map.empty

   def put[T](k: Key[T], v: T) = backingMap += (k -> v)

   def get[T](k: Key[T]): Option[T] = backingMap get k map (_.asInstanceOf[T])
}

scala> val strKey = new Key[String] 
strKey: Key[String] = Key@31028a

scala> val intKey = new Key[Int]
intKey: Key[Int] = Key@7ae77ca4

scala> Registry.put(strKey, "asdf")

scala> Registry.get(strKey)
res0: Option[String] = Some(asdf)

scala> Registry.put(intKey, "asdf")
<console>:10: error: type mismatch;
 found   : Key[Int]
 required: Key[Any]
       Registry.put(intKey, "asdf")

另外,您可以使用未打类型的键,并使用清单将类型信息存储在Map中(正如Daniel所建议的那样):

class Registry[K] {
   import scala.reflect.Manifest

   private var _map= Map.empty[K,(Manifest[_], Any)] 

   def put[T](key: K, item: T)(implicit m: Manifest[T]) {
      _map += (key -> (m, item))
   }

   def get[T](key:K)(implicit m : Manifest[T]): Option[T] = {
      for ((om, v) <- _map get key if om <:< m) 
         yield v.asInstanceOf[T]
   }
}

后一种方法的优点是您可以使用任何内容作为键,并且不必传递原始的键对象。然而,它的缺点是在调用get方法时必须指定值类型。如果您指定了错误的类型,您将得到None,就像键根本不在注册表中一样,而对于有类型的键,则保证可以获取与键关联的任何值。

3

不错!我在我的回答中简化了你的实现,并尝试解释了使用键入密钥方法和存储清单方法之间的区别。 - Aaron Novstrup

1

如果您没有太多的值,可以考虑使用一些成对的HList或类似结构。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接