Scala: неприменимый класс Case по сравнению с ручной реализацией и стиранием типа

Я пытаюсь понять, что Scala делает с классами Case, что делает их каким-то образом невосприимчивыми к предупреждениям об стирании типа.

Допустим, у нас есть следующая простая структура классов. По сути, это Либо :

abstract class BlackOrWhite[A, B]

case class Black[A,B]( val left: A ) extends BlackOrWhite[A,B]

case class White[A,B]( val right: B ) extends BlackOrWhite[A,B]

И вы пытаетесь использовать его так:

object Main extends App {

    def echo[A,B] ( input: BlackOrWhite[A,B] ) = input match {
        case Black(left) => println( "Black: " + left )
        case White(right) => println( "White: " + right )
    }

    echo( Black[String, Int]( "String!" ) )
    echo( White[String, Int]( 1234 ) )
}

Все компилируется и запускается без каких-либо проблем. Однако, когда я сам пытаюсь реализовать метод unapply , компилятор выдает предупреждение. Я использовал следующую структуру классов с тем же классом Main выше:

abstract class BlackOrWhite[A, B]

case class Black[A,B]( val left: A ) extends BlackOrWhite[A,B]

object White {

    def apply[A,B]( right: B ): White[A,B] = new White[A,B](right)

    def unapply[B]( value: White[_,B] ): Option[B] = Some( value.right )

}

class White[A,B]( val right: B ) extends BlackOrWhite[A,B]

При компиляции с флагом -unchecked выдается следующее предупреждение:

[info] Compiling 1 Scala source to target/scala-2.9.1.final/classes...
[warn] src/main/scala/Test.scala:41: non variable type-argument B in type pattern main.scala.White[_, B] is unchecked since it is eliminated by erasure
[warn]         case White(right) => println( "White: " + right )
[warn]                   ^
[warn] one warning found
[info] Running main.scala.Main

Теперь я понимаю стирание типов и Я пытался обойти предупреждение с помощью Manifests (пока безрезультатно), но в чем разница между двумя реализациями? Делают ли кейс-классы что-то, что мне нужно добавить? Можно ли обойти это с помощью манифестов ?

Я даже попытался запустить реализацию класса case через компилятор scala с включенным флагом -Xprint: typer , но неприменимо Метод выглядит примерно так, как я ожидал:

case <synthetic> def unapply[A >: Nothing <: Any, B >: Nothing <: Any](x$0: $iw.$iw.White[A,B]): Option[B] = if (x$0.==(null))
    scala.this.None
else
    scala.Some.apply[B](x$0.right);

Заранее спасибо

19
задан Nycto 9 January 2012 в 02:09
поделиться