2011-03-15 51 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