scala - significa - Clase de caso y argumentos implícitos y coincidencia de patrones
razonamiento implicito (2)
Intenté combinar argumentos implícitos con clases de casos, pero me quedé atascado.
case class C(i: Int)(implicit b: Boolean)
val c1 = C(1)(true)
implicit val b = true
val c2 = C(2)
c1 match {
case C(i)(b) => // doesn´t work
case C(i,b) => // doesn´t work
case C(i) => // works, but wanted: if (b) i else 0
}
De acuerdo con la especificación del lenguaje Scala, se debe al objeto extractor generado por el compilador para las clases de caso: Mi Boolean
implícito no es un miembro de la clase de caso resultante, por lo que tiene que estar en la segunda lista de argumentos (implícita) (que puedo "No se encuentra en el método de aplicación de los objetos complementarios, desafortunadamente):
Una definición de clase de caso de
c[tps](ps1 ). . .(psn)
c[tps](ps1 ). . .(psn)
c[tps](ps1 ). . .(psn)
con los parámetros de tipotps
y los parámetros de valorps
genera implícitamente un objeto extractor (§8.1.8) que se define de la siguiente manera:
object c {
def apply[tps](ps1 ). . .(psn): c[tps] = new c[Ts](xs1 ). . .(xsn)
def unapply[tps](x: c[tps]) =
if (x eq null) scala.None
else scala.Some(x.xs11, . . . , x.xs1k)
}
¿Cómo puedo definir una clase de caso con miembros que se suministran implícitamente en el momento de la creación?
La respuesta de Alex es inteligente, sin embargo, no me gusta mucho _
en el nombre del objeto, me parece que la sintaxis es un poco extraña y recordar que el subrayado hace que la comparación de patrones sea más difícil de usar. (Por supuesto, todo esto es subjetivo, por lo que sus sentimientos pueden variar).
Mi primer enfoque para lidiar con esto fue mover los parámetros implícitos al método de apply
en el objeto compañero.
case class A(i: Int, b: Boolean)
object Foo {
def apply(i: Int)(implicit b: Boolean): Foo = apply(a, b)
}
Pero esto resulta en
Error:(21, 14) double definition:
method apply:(i: Int, b: Boolean)com.workday.cloud.master.package.A and
method apply:(i: Int)(implicit b: Boolean)com.workday.cloud.master.package.A at line 24
have same type after erasure: (i: Int, b: Boolean)com.workday.cloud.master.package.A
case class A(i: Int, b: Boolean)
^
Como sugirió mi amigo Yuriy, podemos solucionar esto agregando un parámetro implícito Unused
adicional.
object A {
implicit object Unused
def apply(i: Int)(implicit b: Boolean, unused: Unused.type): A = apply(i, b)
}
El enfoque que elija depende de usted. Creo que este enfoque permite que el código de mi cliente se vea más natural.
Puede definir una clase de caso con argumentos implícitos, pero como ha descubierto, no están disponibles para la coincidencia de patrones. Aunque siempre puedes escribir tu propio extractor:
case class C(i: Int)(implicit val b: Boolean)
// You can''t call this C because that seat is taken (can''t overload the default unapply)
object C_ {
// In order to be able to select `b` here,
// it needs to be declared as "implicit *val* b: Boolean"
def unapply(in: C) = Some((in.i, in.b))
}
c1 match {
case C_(i, b) => ...
}