Понимание Erasure с классом Generic Case

Для следующего класса случаев:

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"
                       ^

person Kevin Meredith    schedule 13.01.2015    source источник
comment
Как вы думаете, почему он стерт?   -  person Sotirios Delimanolis    schedule 13.01.2015
comment
Я думаю, что Foo попадает в то же ведро, что и List согласно этому вопрос. Опять же, я думаю, но не совсем уверен.   -  person Kevin Meredith    schedule 13.01.2015


Ответы (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.

person Victor Moroz    schedule 13.01.2015

Он стерт. В вашем случае компилятор может статически проверить, что foo является Foo[Int], и выражение сопоставления здесь имеет смысл только с Foo[Int], Foo[_] или Any (AnyRef, scala.Product, scala.Serializable).

Но если вы скроете реальный класс foo, используя, например, базовый класс Any:

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

Вы получите предупреждение:

аргумент непеременного типа String в шаблоне типа Foo[String] не отмечен, так как он удаляется стиранием

и программа напечатает "строку".

person user5102379    schedule 13.01.2015