通常的答案来解决类型擦除是使用清单的帮助。你的情况,你可以做到以下几点:
abstract class TypedFunc[-A:Manifest,+R:Manifest] extends (A => R) {
val retType: Manifest[_] = manifest[R]
val argType: Manifest[_] = manifest[A]
}
object TypedFunc {
implicit def apply[A:Manifest, R:Manifest](f: A => R): TypedFunc[A, R] = {
f match {
case tf: TypedFunc[A, R] => tf
case _ => new TypedFunc[A, R] { final def apply(arg: A): R = f(arg) }
}
}
}
def applyFunc[A, R, T >: A : Manifest](funcs: Traversable[TypedFunc[A,R]])(arg: T): R = {
funcs.find{ f => f.argType <:< manifest[T] } match {
case Some(f) => f(arg.asInstanceOf[A])
case _ => sys.error("Could not find function with argument matching type " + manifest[T])
}
}
val func1 = { s: String => s.length }
val func2 = { l: Long => l.toInt }
val func3 = { s: Symbol => s.name.length }
val funcList = List(func1: TypedFunc[String,Int], func2: TypedFunc[Long, Int], func3: TypedFunc[Symbol, Int])
测试在REPL:
scala> applyFunc(funcList)('hello)
res22: Int = 5
scala> applyFunc(funcList)("azerty")
res23: Int = 6
scala> applyFunc(funcList)(123L)
res24: Int = 123
scala> applyFunc(funcList)(123)
java.lang.RuntimeException: Could not find function with argument matching type Int
at scala.sys.package$.error(package.scala:27)
at .applyFunc(<console>:27)
at .<init>(<console>:14)
...
非常酷。感谢您提供使用Manifests的具体示例! – aaronlevin
这对于Scala 2.9和2.10都适用吗? – aaronlevin
是的。尽管你现在应该(在2.10中)赞成在'Manifest'上使用'TypeTag',但它确实有效。 –