21

考虑这个类:

class DateTime(year: Int, month: Int, day: Int)(hour: Int, minute: Int, second: Int)

如果我想匹配以下内容,该unapply方法会是什么样子:

dt match {
  case DateTime(2012, 12, 12)(12, _, _) => // December 12th 2012, 12 o'clock
  /* ... */
}

我试过这个:

def unapply(dt: DateTime) = 
  Some((dt.year, dt.month, dt.day),(dt.hour, dt.minute, dt.second))

但这并没有真正奏效。

4

3 回答 3

24

案例类仅在第一组参数上匹配(并做其他漂亮的事情):

scala> case class A(i: Int)(j: Int) { }
defined class A

scala> A(5)(4) match { case A(5) => "Hi" }
res14: java.lang.String = Hi

scala> A(5)(4) == A(5)(9)
res15: Boolean = true

如果它不是一个案例类,你可以将 unapply 定义为你想要的任何东西,所以这真的取决于类的实现者。默认情况下,没有 unapply,因此您只能在类型上进行匹配。

如果您想使用漂亮的案例类功能,包括能够对所有内容进行匹配和相等,但有某种划分,您可以嵌套案例类:

case class Time(hour: Int, minute: Int, second: Int) { }
case class Date(year: Int, month: Int, day: Int) { }
case class DateTime(date: Date, time: Time) { }

scala> val dt = DateTime(Date(2011,5,27), Time(15,21,50))
scala> dt match { case DateTime(Date(2011,_,_),Time(h,m,50)) => println(h + ":" + m) }
15:21
于 2011-05-27T19:18:20.017 回答
10

只是以 Rex 的回答为基础,您不仅只能在第一个参数块上进行模式匹配,而且这种行为在很大程度上是设计使然。

更有趣的问题是,为什么 case 类,作为代数数据类型,甚至支持多个参数列表......

没有足够的理由为案例类添加特殊行为,并且多个参数列表非常有用。在生产代码中,此功能通常仅用于提供隐式参数,您很自然不想进行模式匹配。

于 2011-05-27T23:04:16.063 回答
1

它可能不起作用,因为 Scala 没有逗号运算符,并且您正在Some((a,b),(x,y))从提取器返回。如果您Some(((a,b,c),(x,y,z)))改用(即Tuple2[Tuple3[A,B,C],Tuple3[X,Y,Z]]我认为它可能会起作用。

于 2011-05-27T22:36:24.460 回答