期权匹配的Scala类型擦除

时间:2013-09-04 02:38:01

标签: scala

object Test {
  def main(args: Array[String]) {
    val list: List[Double] = List(1.0, 2.0, 3.0, 4.0)
    val none = None

    case class Test()

    val test = Test()

    def f(x: Any) = x match {
        case _: Some[Test] => println("_ matched")
        case None => println("None matched")
    }

    f(list)
    f(none)
    f(test)
  }
}

尝试编译上面的代码会导致“通过擦除消除”编译时警告。

   $>scalac Test.scala
    Test.scala:11: warning: non-variable type argument Test in type pattern
 Some[Test] is unchecked since it is eliminated by erasure
            case _: Some[Test] => println("_ matched")
                    ^
    one warning found

我读过这个备受推崇的Stackoverflow post,但我不明白这里的类型擦除。

2 个答案:

答案 0 :(得分:9)

这警告您,在运行时无法确定值是Some[Test]而不是Some[Int]Some[anything else]。这是由于JVM不知道类型参数(即我们在Java中使用类型擦除的原因相同)。您引用的帖子显示了Scala中提供的解决此类型擦除问题的方法,如果您确实需要确保拥有Some[Test]而不是其他任何子类型的Some。在你的情况下,这似乎并不相关,所以我不会出现警告。

另一方面,更多惯用(和实用!)将如下:

def f(x: Any) = x match {
    case Some(y) => println(s"x matched to Some - wrapped value is $y")
    case None => println("None matched")
}

这与Some[Any]匹配,但也为您提供直接在案例块中使用的包装值。

如果您确实需要确定您的值是Test类型,请尝试围绕TypeTags(例如您提到的链接,或参见here),或者您可以采取有点讨厌的方式isInstanceOf方法:

case Some(y) if (y.isInstanceOf[Test]) => ...

编辑:或

case Some(e: Test) => ...

根据@ senia的回答。

答案 1 :(得分:8)

jvm的运行时,没有Some[Test]Some[String]只有Some[Any]。因此,您无法在Some[Test]上进行匹配。

在这种情况下,您可以匹配Some的内容,如下所示:

case Some(e: Test) => println(s"$e matched")