2011-05-27 25 views
18

考虑这个类:如何模式匹配具有多个参数列表的类?

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)) 

但那真的没用。

回答

21

案例类的比赛(和做他们的其他漂亮的东西)仅在第一组参数:

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 

如果它不是一个案例类,你可以定义不应用以任何你想要的,所以它的真正取决于班级的实施者。默认情况下,没有不适用,所以你只能匹配类型。

如果你想使用漂亮的案例类的功能,包括能够匹配并做一切平等的,但有一些类型的划分,你可以窝案类:

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 
1

它可能没有因为Scala没有逗号操作符,并且您从提取器返回Some((a,b),(x,y))。如果您使用Some(((a,b,c),(x,y,z)))代替(即Tuple2[Tuple3[A,B,C],Tuple3[X,Y,Z]]我想大概会的工作。

9

只是建立在雷克斯的回答,不仅可以只有第一个参数块模式匹配,但这种行为是设计非常多。

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

有没有足够强大的理由来添加特殊行为case类,以及多参数列表练得在生产代码中,这个工具通常只用于提供隐含的参数,而你自然不会想要t o模式匹配。

+3

多个参数列表很好,因为您可以有多个var参数列表。 – 2015-05-17 23:52:21

+0

也许这是一个有点人为的例子,但如果你可以说'case class MyCase [A <:WithBar](a:A)(b:A#Bar)'并且获得所有“漂亮功能”将有可能创建新的实例,如'val x = MyCase(FooWithBar(...))(Bar(...))',而不需要对'A'进行类型注释。使用'MyCase [A <:WithBar](a:A,b:A#Bar)“等签名,您必须使用val x = MyCase [FooWithBar](FooWithBar(...),Bar(...)实例化。 。))',因为类型推断在与'A'类型的参数相同的参数列表中指定时不适用于'A#Bar'。 – falconepl 2015-08-20 07:45:11

+0

避免案件类诱惑的另一个原因。他们不能很好地使用该语言的许多高级功能(或概念)。 – matanster 2016-04-20 10:47:19