2011-03-15 33 views
15

我试图隐含参数与case类结合起来,但我被困。案例类和隐参数和模式匹配

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 
} 

根据Scala的语言规范的编译器生成的提取对象it's到期的情况下的类:我的隐式Boolean不是所得情况下类的成员,所以它必须是在第二个(隐的)参数列表(即我不能在同伴找到object's应用方法,不幸的是):

c[tps](ps1). . .(psn)与类型参数tps和值 参数的情况类定义ps隐含地产生的提取物(§ 8.1.8),其定义为 如下:

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

我如何定义与在创建时隐式地提供会员的情况下,类?

回答

18

您可以定义具有隐含参数的案例类,但正如您发现的,它们不适用于模式匹配。你总是可以编写自己的提取,但:

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) => ... 
} 
+0

其实我觉得你可以* *定义'对象C'覆盖供应'unapply'的情况下级。另外'隐式b'不会自动变成'val b',所以还有一些工作要做。 – 2011-03-15 17:52:50

+0

“无法解决超载不应用” :)至于瓦尔,是的,我是中间的编辑。 :) – 2011-03-15 17:53:55

+1

我想的话,你同样可以写:'C1匹配{情况下,x @ C(I)=>如果(x.b)我还有0}' – Mahdi 2015-12-11 10:22:22

3

Alex的答案是聪明的,但我真的不喜欢的对象名称_,我觉得语法有些奇怪和记忆下划线使模式匹配更多难以使用。 (当然这都是主观的,所以你的感觉可能会有所不同)。

我的第一个办法来处理这个人的隐含参数移动到同伴对象的apply方法。

case class A(i: Int, b: Boolean) 

object Foo { 
    def apply(i: Int)(implicit b: Boolean): Foo = apply(a, b) 
} 

但这会导致

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

正如我的朋友尤里建议,我们可以通过增加一个额外Unused隐含参数解决这个问题。

object A { 
    implicit object Unused 

    def apply(i: Int)(implicit b: Boolean, unused: Unused.type): A = apply(i, b) 
} 

哪种方法你选择的是你的,我觉得这种方法使我的客户端代码看起来更自然。

+0

THX为 “未使用” 的提示! – comonad 2016-10-20 15:21:02

+1

'未使用:单位=()'工作太 – comonad 2016-10-20 15:27:03