Scala:案例类未应用于手动实现和类型擦除
我正在试图了解Scala对Case Classes的作用,这使得它们以类型擦除警告的方式不受影响。
假设我们有以下简单的类结构。这基本上是一个: 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] 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] 使用-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来解决警告(到目前为止还没有用),但是这两个实现有什么区别?案例类是否需要添加内容?这可以用清单来规避吗? 我甚至尝试通过scala编译器运行case类实现,打开了-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); 提前致谢 解决方法
我不能给出完整的答案,但是我可以告诉你,尽管编译器为case类生成一个未应用的方法,但是当它在案例类上匹配时,它不使用该未应用的方法。如果您尝试使用–Browse:typer使用内置情况匹配和您的未应用方法,您将看到一个非常不同的语法树生成(对于匹配),取决于使用哪个。您也可以浏览后期阶段,看看差异依然存在。
为什么Scala不使用内置的unapply我不知道,虽然可能是因为你提出的原因。而且如何解决这个问题,我自己也没办法了。但这是Scala似乎幻想地避免这个问题的原因。 经过实验,显然这个版本的unapply作品,虽然我有点困惑为什么: def unapply[A,B](value: BlackOrWhite[A,B]): Option[B] = value match { case w: White[_,_] => Some(w.right) case _ => None } 你的未应用的困难是,不知何故编译器必须相信,如果一个White [A,B]扩展了一个BlackOrWhite [C,D],那么B与D相同,这显然是编译器能够在这个版本,但不在你的。不知道为什么 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |