处理类型擦除的一种简单方法是创建一个未参数化的类。它并不完美,但它有效。让它成为一个扩展 Function2 的 case 类,直接使用或在模式匹配中使用都不会太笨重
scala> case class Operation(f : (Int,Int) => Int) extends ((Int,Int) => Int) {
| def apply(x : Int, y : Int) = f(x,y)
| }
defined class Operation
scala> def add = Operation(_ + _)
add: Operation
scala> val y = add(7,3)
y: Int = 10
scala> val elements = List(1, add, 2)
elements: List[Any] = List(1, <function2>, 2)
scala> for (a <- elements) yield a match {
| case Operation(f) => f(1,2)
| case x : Int => x
| }
res0: List[Int] = List(1, 3, 2)
限制是您必须在丢失类型之前“装箱”操作,而不是之后。此外,您最终会为每个具体函数类型提供一个类。
另一个可以说更好的解决方案是不丢失类型信息。使用 Either 来保留静态类型信息。
scala> val elements : List[Either[Int, (Int, Int) => Int]] = List(Left(1), Right(_ + _), Left(2))
elements: List[Either[Int,(Int, Int) => Int]] = List(Left(1), Right(<function2>), Left(2))
scala> for (a <- elements) yield a match {
| case Right(f) => f(1,2)
| case Left(x) => x
| }
res1: List[Int] = List(1, 3, 2)
这里的限制是,如果您的 List 可以有超过 2 种类型,它就会变得笨拙。但它有效地避免了强制 Scala 成为动态类型语言,这与之前的解决方案不同。