Scala Any => 本机格式
Scala Any => native format
我有一个类型为 Map[_, Any]
的地图,我想提取其原始格式的值(不求助于 .asInstanceOf[_]
)。
像这样...
val m: Map[String, Any] = Map("i" -> 1, "s" -> "test")
val i: Option[Int] = m.get("i")
val s: Option[String] = m.get("s")
显然失败了。
我不喜欢这种方法,但我想我可以做这样的事情......但即使这样仍然出现 Any
而不是 Int
或 String
.
trait MyType[A] {
def value: A
}
implicit class MyInt(i: Int) extends MyType[Int] { def value: Int = i }
implicit class MyString(s: String) extends MyType[String] { def value: String = s }
val m: Map[String, MyType[_]] = Map("i" -> 1, "s" -> "test")
val i: Option[Int] = m.get("i").map(_.value)
val s: Option[String] = m.get("s").map(_.value)
然后我想也许 Map
...
有一些包装
case class MyMap(m: Map[String, Any]) {
def get[A](k: String)(implicit ev: Option[Any] => Option[A]): Option[A] = m.get(k)
}
但结果仍然是 Any
。我只是不知道如何转换 Any => native。
所以我的问题是...
- 为什么会失败?
- 以原始格式获取值的更好方法是什么?最简单的 and/or 没有外部依赖是理想的...但老实说,我对任何事情都持开放态度(尽管我现在仍在使用 scala 2.11)。
谢谢!
由于评论中已解释的原因,您无法猜测运行时类型 - 此信息不存在,一旦 Any
,所有类型信息都将丢失,您无能为力它。
因此,您必须自己提供预期的类型。 .as[T]
辅助方法怎么样?
// This code is specifically for 2.11, please don't use it for more recent versions,
// see link below.
val m: Map[String, Any] = Map("i" -> 1, "s" -> "test")
import scala.reflect.{ ClassTag, classTag }
implicit class As(a: Any) {
def as[T](implicit ct: ClassTag[T]): Option[T] = ct.unapply(a)
}
println(m("i").as[Int].map(_ + 41).get)
println(m("s").as[String].map("This is a " + _).get)
这将打印
42
This is a test
简要说明:
As
包装器“拉皮条”所有对象,并为所有对象附加一个 .as
方法。
unapply
在 Option
中进行检查、转换和包装。
它不适用于 List[Int]
与 List[String]
等泛型类型,因为此信息在运行时根本不可用。
编辑:感谢@MarioGalic 大大简化了解决方案。
我有一个类型为 Map[_, Any]
的地图,我想提取其原始格式的值(不求助于 .asInstanceOf[_]
)。
像这样...
val m: Map[String, Any] = Map("i" -> 1, "s" -> "test")
val i: Option[Int] = m.get("i")
val s: Option[String] = m.get("s")
显然失败了。
我不喜欢这种方法,但我想我可以做这样的事情......但即使这样仍然出现 Any
而不是 Int
或 String
.
trait MyType[A] {
def value: A
}
implicit class MyInt(i: Int) extends MyType[Int] { def value: Int = i }
implicit class MyString(s: String) extends MyType[String] { def value: String = s }
val m: Map[String, MyType[_]] = Map("i" -> 1, "s" -> "test")
val i: Option[Int] = m.get("i").map(_.value)
val s: Option[String] = m.get("s").map(_.value)
然后我想也许 Map
...
case class MyMap(m: Map[String, Any]) {
def get[A](k: String)(implicit ev: Option[Any] => Option[A]): Option[A] = m.get(k)
}
但结果仍然是 Any
。我只是不知道如何转换 Any => native。
所以我的问题是...
- 为什么会失败?
- 以原始格式获取值的更好方法是什么?最简单的 and/or 没有外部依赖是理想的...但老实说,我对任何事情都持开放态度(尽管我现在仍在使用 scala 2.11)。
谢谢!
由于评论中已解释的原因,您无法猜测运行时类型 - 此信息不存在,一旦 Any
,所有类型信息都将丢失,您无能为力它。
因此,您必须自己提供预期的类型。 .as[T]
辅助方法怎么样?
// This code is specifically for 2.11, please don't use it for more recent versions,
// see link below.
val m: Map[String, Any] = Map("i" -> 1, "s" -> "test")
import scala.reflect.{ ClassTag, classTag }
implicit class As(a: Any) {
def as[T](implicit ct: ClassTag[T]): Option[T] = ct.unapply(a)
}
println(m("i").as[Int].map(_ + 41).get)
println(m("s").as[String].map("This is a " + _).get)
这将打印
42
This is a test
简要说明:
As
包装器“拉皮条”所有对象,并为所有对象附加一个.as
方法。unapply
在Option
中进行检查、转换和包装。
它不适用于 List[Int]
与 List[String]
等泛型类型,因为此信息在运行时根本不可用。
编辑:感谢@MarioGalic 大大简化了解决方案。