我如何使用重载的case类构造函数仍然使用模式匹配?

时间:2013-03-04 10:00:38

标签: scala pattern-matching overloading case-class

当我找到这个例子时,我试图学习模式匹配。似乎case类模式匹配不适用于重载的case类构造函数。

case class MyClass(var first:String, var last:String){
 def this(first: String) = this(first, "")
 override def toString = "First: "+ first + " Last:" +last
}

val myClassTwo = new MyClass("a", "b")
myClassTwo match {
   case MyClass(a,b) => println("two constructor matched")
   case MyClass(a) => println("one constructor matched")
   case _ => println("Not matched")
  } 

我收到编译错误“模式MyClass的参数错误(第一个:String,last:String)在”case MyClass(a)“行。我期望模式匹配适用于重载的构造函数,但它不是按照我的预期工作。有人可以解释一下这种行为吗?

另外,我得到一个构造函数参数的错误结果。

 val myClassOne = new MyClass("a")      
  myClassOne match {
   case MyClass(a,b) => println("two constructor matched")
   case _ => println("Not matched")
  } 

即使myClassOne只有一个agrument,这也会产生“两个匹配的构造函数”。请解释一下。

2 个答案:

答案 0 :(得分:17)

要了解发生了什么,您需要知道案例类的模式匹配是名为unapply的方法的语法。这在A Tour of Scala: Extractor Objects中解释。

使用REPL,您可以看到编译器在unapply的伴随对象上生成了MyClass方法,该方法对应于主构造函数的参数:

scala> MyClass.unapply _
res0: MyClass => Option[(String, String)] = <function1>

但编译器不会为您定义的任何辅助构造函数生成提取器(使用this())。如果您尝试自己定义一个额外的unapply,您将看到原因 - 您不能使用具有完全相同参数的另一个(MyClass的实例)重载该方法。

使用辅助构造函数new MyClass("a")创建实例时,它仍然是MyClass的完全构造的实例,因此生成的unapply方法仍然有效。 case MyClass(a,b)中的模式将a"a"匹配,b""匹配。

答案 1 :(得分:3)

Ben的答案很完美......

您仍然可以使用case class找到与_匹配的方法,以获取您不关心的参数...

myClassOne match {
   case MyClass("a","b") => println("two constructor matched")
   case MyClass("a",_) => println("one constructor matched")
   case _ => println("Not matched")
  }