Я пытаюсь понять, что делает Scala с Case-классами, что делает их каким-то образом невосприимчивыми к предупреждениям об удалении типов.
Допустим, у нас есть следующая простая структура классов.По сути это Either
:
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
Теперь я понимаювведите erasure, и я попытался обойти предупреждение с помощью Manifests
(пока безрезультатно), но в чем разница между двумя реализациями?Классы дел делают то, что мне нужно добавить?Можно ли обойти это с помощью Manifests
?
Я даже пытался запустить реализацию класса case через компилятор scala с включенным флагом -Xprint:typer
, но метод unapply
выглядит почти так, как я ожидал:
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);
Заранее спасибо