给定以下类型和实例:
type operation = (Int, Int) => Int
def add: operation = _ + _
Run Code Online (Sandbox Code Playgroud)
如果我尝试匹配case语句中的操作,Scala会因为类型擦除而抱怨未经检查的键入:
for (a <- elements) a match {
case o: operation => // do stuff
}
Run Code Online (Sandbox Code Playgroud)
有没有办法实现这种基于函数的打字,同时在case语句中易于擦除?
注意,这与此线程类似.
处理类型擦除的一种简单方法是创建一个unparamaterized类.它并不完美,但它确实有效.使它成为一个扩展Function2的案例类,它甚至不会太直率地使用直接或模式匹配
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)
Run Code Online (Sandbox Code Playgroud)
限制是你必须在失去类型之前进行"盒装"操作,而不是之后.此外,每个具体的函数类型最终会有一个类.
另一个可以说是更好的解决方案是不丢失类型信息.使用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)
Run Code Online (Sandbox Code Playgroud)
这里的限制是,如果你的List可以拥有超过2种类型,它会变得笨拙.但与以前的解决方案不同,它有效地避免了强制Scala成为动态类型语言.
| 归档时间: |
|
| 查看次数: |
1043 次 |
| 最近记录: |