2011-05-27 14 views
18

Considere esta clase:¿Cómo se empareja una clase con varias listas de argumentos?

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

¿cómo la mirada unapply método similar, si me gustaría hacer coincidir contra algo como:

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

He intentado esto:

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

Pero eso realmente no funcionó.

Respuesta

21

Caso clases partido (y hacer sus otras cosas ingeniosas) sólo en el primer conjunto de parámetros:

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 

Si no es una clase de caso, se puede definir el cancelar la aplicación a ser lo que quieras, por lo que es realmente depende del implementador de la clase. De forma predeterminada, no hay ninguna aplicación, por lo que puede coincidir solo en el tipo.

Si desea utilizar las características de clase caso ingeniosas incluyendo el ser capaz de igualar y hacer la igualdad en todo, pero tienen algún tipo de división, se podía clases de casos de nidos:

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

Es probable que no lo hizo trabajo porque Scala no tiene operador de coma, y ​​está devolviendo Some((a,b),(x,y)) desde el extractor. Si utilizó Some(((a,b,c),(x,y,z))) lugar (es decir, un Tuple2[Tuple3[A,B,C],Tuple3[X,Y,Z]] Creo que sería probablemente el trabajo.

9

Sólo para construir sobre la respuesta de Rex, no sólo se puede solamente el ajuste de patrones en el primer bloque de parámetros, pero este comportamiento es en gran medida por el diseño.

La pregunta más interesante es por qué clases de casos, como tipos de datos algebraicos, incluso soportan múltiples listas de parámetros ...

no hay justificación lo suficientemente fuerte como para añadir un comportamiento especial para las clases de casos, y múltiples listas de parámetros resultan ser bastante útil. En el código de producción, esta función a menudo solo se usa para proporcionar argumentos implícitos, lo que naturalmente no querría t o coincidencia de patrón.

+3

Las listas de parámetros múltiples son agradables porque puede tener múltiples listas de var args. –

+0

Quizás sea un ejemplo poco artificial, pero si pudiera decir 'clase de caso MyCase [A <: WithBar] (a: A) (b: A # Bar)' y obtener todas las "funciones ingeniosas" de la caja, entonces Sería posible crear nuevas instancias como 'val x = MyCase (FooWithBar (...)) (Bar (...))', sin anotación de tipo para 'A'. Con una firma como 'MyCase [A <: WithBar] (a: A, b: A # Bar)', tiene que instanciar con 'val x = MyCase [FooWithBar] (FooWithBar (...), Bar (.. .)) ', porque la inferencia de tipo no funcionaría para' A # Bar' cuando se especifica en la misma lista de parámetros como parámetro de tipo 'A'. – falconepl

+0

Otra razón para evitar la tentación de clase de caso. No funcionan bien con muchas características avanzadas (o conceptos) del lenguaje. – matanster

Cuestiones relacionadas