在Scala中获取泛型类型的特定简单名称

Ben*_*ith 5 generics scala

是否可以在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")
Run Code Online (Sandbox Code Playgroud)

显然,如果我可以在不必将其传入的情况下解决"用户"问题会更容易.

Did*_*ont 9

可以从Manifest(或ClassManifest)中检索类名称manifest.erasure.getName(擦除是Class实例).例如

def className[A : ClassManifest] = classManifest[A].erasure.getName
Run Code Online (Sandbox Code Playgroud)

编辑:看过Derek的回答,这使得erasure.getName这个东西看起来相当愚蠢.我不考虑toString.我仍然希望以下内容可能会引起关注

使用ClassManifest和之间的区别在于Manifest,Manifest对于泛型类,类型参数保证可用,而它们是最好的努力ClassManifest(比较typeParameters两个类中的签名).这种保证的缺点是Manifest可能无法隐含地使用a 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)
Run Code Online (Sandbox Code Playgroud)

这样,fromMap只有当a Builder可用于此特定类时,调用才会编译,而不是使用a失败MatchError.


Jak*_*ene 7

对于那些从 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"))
Run Code Online (Sandbox Code Playgroud)


skw*_*won 5

对于 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
Run Code Online (Sandbox Code Playgroud)

执行示例:

scala> name[String]
res5: String = String

scala> fullName[String]
res6: String = java.lang.String
Run Code Online (Sandbox Code Playgroud)

参考: http: //www.scala-lang.org/api/2.11.0/scala-reflect/index.html