Существует (по крайней мере, один) другой способ, даже если он не слишком приятен и не совсем безопасен для типов:
import scala.reflect.Manifest
object Reified {
def foo[T](p:List[T])(implicit m: Manifest[T]) = {
def stringList(l: List[String]) {
println("Strings")
}
def intList(l: List[Int]) {
println("Ints")
}
val StringClass = classOf[String]
val IntClass = classOf[Int]
m.erasure match {
case StringClass => stringList(p.asInstanceOf[List[String]])
case IntClass => intList(p.asInstanceOf[List[Int]])
case _ => error("???")
}
}
def main(args: Array[String]) {
foo(List("String"))
foo(List(1, 2, 3))
}
}
Неявный параметр манифеста можно использовать для «повторного определения» стертого типа итаким образом взломать вокруг стирания.Вы можете узнать немного больше об этом во многих сообщениях в блогах, например, this .
. Что происходит, так это то, что явный параметр может вернуть вам то, что было до удаления.Тогда простая отправка, основанная на T, для различных реальных реализаций сделает все остальное.
Вероятно, есть более хороший способ сопоставления с образцом, но я еще не видел его.То, что обычно делают люди, это сопоставление с m.toString, но я думаю, что хранить классы немного чище (даже если это немного более многословно).К сожалению, документация Манифеста не слишком детализирована, возможно, в ней также есть что-то, что может упростить ее.
Большим недостатком является то, что он не совсем безопасен для типов: foo будет доволен любым T, если вы не справитесь с этим, у вас будут проблемы.Я думаю, что это можно обойти с некоторыми ограничениями на T, но это еще больше усложнит это.
И, конечно, все это тоже не слишком приятно, я не уверен, стоит ли это делать, особенно если вы ленивы; -)