使用通用案例类理解擦除

时间:2015-01-13 01:30:55

标签: scala erasure

对于以下案例类:

scala> case class Foo[T](name: String) {}
defined class Foo

scala> val foo = Foo[Int]("foo")
foo: Foo[Int] = Foo(foo)

为什么Scala会让我(正如我认为的那样)在Foo[Int]上匹配?是不是Int已删除?

scala> foo match { 
     |   case _: Foo[Int] => "foo"
     |   case _        => "bar"
     | }
res2: String = foo

但是当包含另一个模式匹配的情况时,它会显示编译时错误吗?

scala> foo match { 
     |  case _: Foo[String] => "string"
     |  case _: Foo[Int]    => "int"
     |  case _              => "other"
     | }
<console>:12: warning: non-variable type argument String in type pattern Foo[String] is unchecked since it is eliminated by erasure
               case _: Foo[String] => "string"
                       ^
    <console>:12: error: pattern type is incompatible with expected type;
     found   : Foo[String]

 required: Foo[Int]
               case _: Foo[String] => "string"
                       ^

2 个答案:

答案 0 :(得分:2)

  class SuperFoo;
  case class Foo[T](name: String) extends SuperFoo {}
  val foo: SuperFoo = Foo[Int]("foo")
  foo match {
    case _: Foo[String] => "foo"
    case _        => "bar"
  }  //> res0: String = foo + warning

在您的情况下,编译器知道foo的确切类型。

答案 1 :(得分:0)

它被删除了。在您的情况下,编译器可以静态检查foo是否为Foo[Int],此处匹配表达式仅对Foo[Int]Foo[_]AnyAnyRef有意义,scala.Productscala.Serializable)。

但是如果你使用基类foo隐藏Any真实类:

val foo: Any = Foo[Int]("foo")
val res = foo match {
  case _: Foo[String] => "string"
  case _              => "other"
}
println(res) // string

你会收到警告:

  

非变量类型参数类型为模式Foo [String]的字符串   未经检查,因为它被删除消除了

程序将打印&#34; string&#34;。