是否可以在Scala中获取泛型类的类型名称?我知道在类型擦除的Java中这是不可能的,但我希望Scala会是另一种情况。
目前我必须做类似的事情:
trait Model
case class User(id: String) extends Model
def fromMap[M<:Model : Manifest](data: Map[String, String], modelType: String) = {
modelType match {
case "user" => User(data.get("id").get)
}
}
val user = fromMap[User](Map("id" -> "id1"), "user")
显然,如果我可以在不必将其传入的情况下解决“用户”问题会更容易。
答案 0 :(得分:9)
可以使用manifest.erasure.getName
从清单(或ClassManifest)中检索类名(擦除是类实例)。例如
def className[A : ClassManifest] = classManifest[A].erasure.getName
编辑:看过Derek的回答,这使得erasure.getName的内容看起来相当愚蠢。我不考虑toString。我仍然希望以下内容可能会引起人们的兴趣
使用ClassManifest
和Manifest
之间的区别在于,Manifest
对于泛型类,类型参数保证可用,而它们是{{1 (比较两个类中ClassManifest
的签名)。这种保证的缺点是typeParameters
可能不会隐含地显示Manifest
。
您是否考虑过使用类型类?
ClassManifest
这样,只有trait BuilderFromMap[A] {def build(data: Map[String, String]): A}
// or better, return Option[A], accounting for possible failure
object User {
implicit val Builder extends BuilderFromMap[User] {...}
}
def fromMap[A](data: Map[String, String])(implicit builder: BuilderFromMap[A])
= builder.build(data)
可用于此特定类,而不是fromMap
失败时,才会编译对Builder
的调用。
答案 1 :(得分:2)
这应该有用(但我必须编辑你的代码才能猜出你想要的东西):
trait Model
case class User(id: String) extends Model
object Main extends App {
def fromMap[M <: Model](data: Map[String, String])(implicit m: reflect.Manifest[M]): Model = {
m.toString match {
case "User" => User(data.get("id").get)
}
}
val user = fromMap[User](Map("id" -> "id1"))
println(user)
}
但基于我遇到的麻烦,我相信有人可以做得更好:)
答案 2 :(得分:1)
对于那些从使用Scala 2.12.x或2.13.x的世界来问这个问题的人,ClassTag[T]
是执行此操作的首选方法。
import scala.reflect._
trait Model
case class User(id: String) extends Model
def fromMap[M <: Model : ClassTag](data: Map[String, String]) = {
val modelType = implicitly[ClassTag[M]].runtimeClass.getSimpleName
modelType match {
case "User" => User(data("id"))
}
}
val user = fromMap[User](Map("id" -> "id1"))
答案 3 :(得分:0)
对于Scala 2.11,以下代码有效:
import scala.reflect.runtime.universe.{typeOf, TypeTag}
def name[T: TypeTag] = typeOf[T].typeSymbol.name.toString
def fullName[T: TypeTag] = typeOf[T].typeSymbol.fullName
执行示例:
scala> name[String]
res5: String = String
scala> fullName[String]
res6: String = java.lang.String
价: http://www.scala-lang.org/api/2.11.0/scala-reflect/index.html