当模式匹配参数化案例类时,Scala“不接受参数”

时间:2014-04-29 22:09:03

标签: scala

我有以下代码:

sealed trait A

case class B[T](v: T) extends A
case class C[T](v: T) extends A

object Test {
  def swap(a: A): A = a match {
    case a: B[t] => C[t](a.v) // works!
    case C[t](v) => B[t](v) // error: C[t] does not take parameters
  }
}

我希望这两种情况都失败,或者两种情况都能奏效。第二种情况的错误含义是什么?是否有语法解构参数化案例类?

注意:这里,' t'小写是必不可少的。如果它是' T',检查员将在方法的类型参数中查找它。

2 个答案:

答案 0 :(得分:6)

执行a match { case C(v) => ??? }时,您实际上会调用unapply随播广告对象的C方法,如下所示:C.unapply(a) match {Some(v) => ???}

只有一个C个对象,而不是C[t]的整个系列。没有任何对象可以称为C[Int],因此case C[t](v) =>没有意义。

在您的示例中,您使用B[t]作为类型,而不是模式,以及它的工作原理。请注意,虽然匹配可能会成功,但由于类型擦除,您无法在t中获得任何内容。

当你调用C[t](a.v)时,首先,编译器会删除类型t,其次,这会被重写为对伴随对象的apply方法的调用:{{ 1}}。请注意,type参数位于方法调用上,而不是在对象上。

答案 1 :(得分:1)

简单地说,它不是语言的一部分。

在此位置使用时,编译器正在查找环境中的类型,就好像它是通常的大写类型一样。您尝试执行的类型捕获似乎仅适用于案例陈述的case x:Y[z] => ...形式。

以这种方式进行类型捕获并不是该语言的一个众所周知的部分,并让我运行到Scala reference document以获取详细信息(第8.3节)。我个人觉得这里大小写的区别不是我喜欢的。

在您的示例中,t采用Any类型,因为A无法提供参数的类型信息。