case类,模式匹配和斯卡拉
问题描述:
令行禁止构造他们似乎
不混那么好:case类,模式匹配和斯卡拉
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")
}
的问题是,模式匹配和curried的论点似乎并不奏效。有没有解决这个问题的方法?
答
这是怎么回事?
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
}
答
您可以使用普通的案例类,只需定义一个具有多个参数列表的工厂方法。
+0
可能我们可以补充一点,如果工厂方法在伴随对象中声明,就不能使用'apply'进行升级(因为它会和第其中一个表示感谢案例分类)。 – Nicolas
答
如果你看一下B类创建不应用功能的签名,你会看到,它是:unapply(x$0: Q): Option[Int]
。因此,unapply函数可以处理案例类的第一个参数范围。
它由阶规范(第5.3.2节)证实:
的情况下类 的第一个参数部分形式参数被称为元素;他们被特别对待。首先, 这个参数的值可以作为构造函数模式的字段提取出来。
它声称只有第一个参数部分可通过提取器。
几种解决方法:
- uncurry您的参数
- ,如果你要测试的2个值使用带保护与模式匹配:
case [email protected](3) if x.b == "bazinga" => ...
- 使用一个普通的类,并定义自己的伴侣对象的自己申请/不申请
你的第一个例子可以工作,但是我不能在case语句中访问B.a和B.b,而不做一些丑陋的类型转换。另外,在你的编辑中,我不确定我是否理解为什么构造函数模式没有被粘贴。是因为不适用? –
说实话,我不知道它为什么起作用。我通过反复试验偶然发现了它。这绝对是在Scala规范中的某处提到的。如果它与您的案例相关,您可能想查看它。 – agilesteel
是的,您在case语句中使用的模式是由unapply函数的结果给出的模式。它永远不会被咖喱。 scala规范中的相应部分是§8.1.8 – Nicolas