14

他们似乎并没有很好地混合:

abstract class A
case class B (var a: Int)(var b: String) extends A
case class C extends A

以下将不起作用:

B(1)("1") match {
  case B(a)(b) => print("B")
  case C() => print("C")
}

问题是模式匹配和柯里化参数似乎不起作用。有解决办法吗?

4

3 回答 3

12

如果您查看为 B 类创建的 unapply 函数的签名,您会看到它是:unapply(x$0: Q): Option[Int]。因此, unapply 函数适用于案例类的第一个参数范围。

Scala 规范(§5.3.2)确认了这一点:

案例类的第一个参数部分中的形参称为元素。他们受到特殊对待。首先,可以将这样一个参数的值提取为构造函数模式的字段。

它清楚地声称只有第一个参数部分可通过提取器获得。

几种解决方法:

  • 取消你的参数
  • 如果要测试 2 个值,请使用与 guard 匹配的模式:case x@B(3) if x.b == "bazinga" => ...
  • 使用普通类并使用您自己的应用/取消应用定义您自己的伴随对象
于 2011-09-01T13:10:04.267 回答
7

这有什么问题?

def m(a: A) = a match {
  case b: B => print("B")
  case c: C => print("C")
}

我只是问,因为您没有要求比这更多的功能。

编辑

这可能会有所帮助:

object Dog {
   def apply(name: String)(size: Int) = new Dog(name)(size)
   def unapply(dog: Dog) = Some(dog.name, dog.size)
}
class Dog(val name: String)(var size: Int)

现在你可以像这样创建狗:

new Dog("Snoopy")(10) 

或像这样:

Dog("Snoopy")(10)

但是当你对狗进行模式匹配时,构造函数模式不会被柯里化。

Dog("Snoopy")(10) match {
   case Dog(a, b) => // do sth with a or b
}
于 2011-09-01T12:53:07.077 回答
2

你可以使用一个普通的案例类,只定义一个带有多个参数列表的工厂方法。

于 2011-09-01T11:52:45.900 回答