[英]Get the specific simple name of a generic type in 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")
顯然,如果我可以在不必將其傳入的情況下解決“用戶”問題會更容易。
可以使用manifest.erasure.getName
(擦除是Class實例)從Manifest(或ClassManifest)中檢索類名。 例如
def className[A : ClassManifest] = classManifest[A].erasure.getName
編輯 :看過Derek的回答,這使得erasure.getName這個東西看起來相當愚蠢。 我不考慮toString。 我仍然希望以下內容可能會引起關注
兩者的區別ClassManifest
和Manifest
的是,在Manifest
的泛型類,類型參數都保證是可用的,而他們在盡最大努力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)
這樣,只有當Builder
可用於此特定類時,才會編譯對fromMap
調用,而不是使用MatchError
失敗。
這應該工作(但我必須編輯你的代碼,以猜測你想要的):
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)
}
但基於我遇到的麻煩,我相信有人可以做得更好:)
對於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
對於那些來自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"))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.