Get the specific simple name of a generic type in Scala
Class name can be retrieved from a Manifest (or a ClassManifest) with manifest.erasure.getName
(erasure is the Class instance). For instance
def className[A : ClassManifest] = classManifest[A].erasure.getName
Edit : Seen Derek's answer, which makes this stuff with erasure.getName look rather stupid. I didn't consider toString. Still I hope what follows may be of interest
The difference between using ClassManifest
and Manifest
is that in the Manifest
for a generic class, the type parameter are guaranteed to be available, while they are best effort in ClassManifest
(compare signatures of typeParameters
in both classes). The drawback of this guarantee is that a Manifest
might not be implicitly available where a ClassManifest
would be.
Have you considered using typeclasses instead?
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)
This way, calls to fromMap
will compile only if a Builder
is available for this particular class, rather than fail with a MatchError
.
For those of you coming to this question from a world with Scala 2.12.x or 2.13.x, ClassTag[T]
is the preferred way to do this.
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"))
For Scala 2.11, following code works:
import scala.reflect.runtime.universe.{typeOf, TypeTag}
def name[T: TypeTag] = typeOf[T].typeSymbol.name.toString
def fullName[T: TypeTag] = typeOf[T].typeSymbol.fullName
Execution example:
scala> name[String]
res5: String = String
scala> fullName[String]
res6: String = java.lang.String
Ref: http://www.scala-lang.org/api/2.11.0/scala-reflect/index.html