期权匹配的Scala类型擦除

Kev*_*ith 5 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)
  }
}
Run Code Online (Sandbox Code Playgroud)

尝试编译上面的代码会导致"擦除"编译时警告.

   $>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
Run Code Online (Sandbox Code Playgroud)

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

Sha*_*nds 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")
}
Run Code Online (Sandbox Code Playgroud)

这匹配Some[Any],但也提供了包装值,您可以直接在案例块中使用.

如果您确实需要确保您的值是Test类型,请尝试围绕TypeTags(您提到的链接,或者在此处查看),或者您可以采用有点讨厌的isInstanceOf方法:

case Some(y) if (y.isInstanceOf[Test]) => ...
Run Code Online (Sandbox Code Playgroud)

编辑:或

case Some(e: Test) => ...
Run Code Online (Sandbox Code Playgroud)

按照@ senia的回答.

  • @Kevin:如果你想使用`y`作为`Test`的实例,你应该检查它是否使用`isInstanceOf`,然后使用`asInstanceOf`将其强制转换为`Test`.这很冗长.并且`asInstanceOf`不是类型安全的:编译器不会强制你在`asInstanceOf`之前使用`isInstanceOf`.结构模式匹配是类型安全的:如果您正在做一些危险的事情,您将收到警告. (3认同)

sen*_*nia 9

在运行时,jvm没有Some[Test]Some[String]只有Some[Any].所以你无法匹敌Some[Test].

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

case Some(e: Test) => println(s"$e matched")
Run Code Online (Sandbox Code Playgroud)

  • @Kevin:是的,就像任何其他变量类型一样.Scala编译器将`case Some(e:Test)`重写为`if(arg.isInstanceOf [Some [_]] && arg.asInstanceOf [Some [Any]].get.isInstanceOf [Test]){val e = arg .asInstanceOf [Some [Any]].get.asInstanceOf [Test] ...}`. (3认同)