scala – 它是一个类型检查错误吗?
发布时间:2020-12-16 18:08:23 所属栏目:安全 来源:网络整理
导读:我把它缩小到下面的代码: trait A[T] { def apply(t: T): Int}sealed trait P { def apply(): Int}case class I[T](a: A[T],t: T) extends P { def apply: Int = a(t)}case class X[T1,T2](a1: A[T1],a2: A[T2]) extends A[(T1,T2)] { def apply(t: (T1,T2)
我把它缩小到下面的代码:
trait A[T] { def apply(t: T): Int } sealed trait P { def apply(): Int } case class I[T](a: A[T],t: T) extends P { def apply: Int = a(t) } case class X[T1,T2](a1: A[T1],a2: A[T2]) extends A[(T1,T2)] { def apply(t: (T1,T2)): Int = t match { case (t1,t2) => a1(t1) + a2(t2) } } object m { def apply(p1: P,p2: P): P = (p1,p2) match { case (I(a1,t1),I(a2,t2)) => I(X(a1,a2),(t2,t1)) // <-- Here } } 如您所见,我在标有< - Here的行中有一个类型错误.然而,代码编译时甚至没有警告,并且在运行时因ClassCastException而失败.代码: case class E() extends A[Int] { def apply(t: Int): Int = t } case class S() extends A[String] { def apply(t: String): Int = t.length } object Test { def apply() = { val pe: P = I(E(),3) val ps: P = I(S(),"abcd") val pp: P = m(pe,ps) pp() } } 我知道当模式匹配scala有时无法检查值是否为正确类型时,但这通常会导致编译器警告. 那么,这是一个错误,还是我想念一些东西? 更新:我担心的是我可以犯一个类型错误,编译器甚至不会警告我.我明白(t1,t2)是正确的顺序;但如果我写得不正确,我会在执行程序之前发现它,甚至可能更晚,尽管它显然是一个类型错误. 解决方法
也许缺乏警告与此有关:
https://issues.scala-lang.org/browse/SI-9188 它似乎没有对A上的类型参数做任何有用的事情,除非它可以静态地证明你弄错了. 这里的最后一场比赛应警告: scala> val i = I(E(),42) i: I[Int] = I(E(),42) scala> i match { case I(a: A[Int],x) => } scala> i match { case I(a: A[String],x) => } <console>:15: warning: non-variable type argument String in type pattern A[String] is unchecked since it is eliminated by erasure i match { case I(a: A[String],x) => } ^ <console>:15: error: pattern type is incompatible with expected type; found : A[String] required: A[Int] i match { case I(a: A[String],x) => } ^ scala> (i: P) match { case I(a: A[String],x) => } <console>:15: warning: non-variable type argument String in type pattern A[String] is unchecked since it is eliminated by erasure (i: P) match { case I(a: A[String],x) => } ^ <console>:15: error: pattern type is incompatible with expected type; found : A[String] required: A[Any] Note: String <: Any,but trait A is invariant in type T. You may wish to define T as +T instead. (SLS 4.5) (i: P) match { case I(a: A[String],x) => } ^ scala> (i: P) match { case I(a: A[Int],x) => } <console>:15: warning: non-variable type argument Int in type pattern A[Int] is unchecked since it is eliminated by erasure (i: P) match { case I(a: A[Int],x) => } ^ <console>:15: error: pattern type is incompatible with expected type; found : A[Int] required: A[Any] Note: Int <: Any,but trait A is invariant in type T. You may wish to define T as +T instead. (SLS 4.5) (i: P) match { case I(a: A[Int],x) => } ^ scala> (i: P) match { case I(a: A[_],x) => } scala> (i: P) match { case I(a: A[Any],x) => } 只是添加: scala> (i: P) match { case I(a: A[Any],x) => a("foo") } java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:105) at E.apply(<console>:33) ... 33 elided (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |