2011-09-01 122 views
13
令行禁止構造他們似乎

不混那麼好:case類,模式匹配和斯卡拉

abstract class A 
case class B (var a: Int)(var b: String) extends A 
case class C extends A 

下將無法正常工作:

B(1)("1") match { 
    case B(a)(b) => print("B") 
    case C() => print("C") 
} 

的問題是,模式匹配和curried的論點似乎並不奏效。有沒有解決這個問題的方法?

回答

7

這是怎麼回事?

def m(a: A) = a match { 
    case b: B => print("B") 
    case c: C => print("C") 
} 

我只問,因爲你沒有要求比這更多的功能。

編輯

這可以幫助:

object Dog { 
    def apply(name: String)(size: Int) = new Dog(name)(size) 
    def unapply(dog: Dog) = Some(dog.name, dog.size) 
} 
class Dog(val name: String)(var size: Int) 

現在你可以創建或者狗這樣的:

new Dog("Snoopy")(10) 

或像這樣:

Dog("Snoopy")(10) 

但是,當你對狗的模式匹配時,構造函數模式是而不是咖喱。

Dog("Snoopy")(10) match { 
    case Dog(a, b) => // do sth with a or b 
} 
+0

你的第一個例子可以工作,但是我不能在case語句中訪問B.a和B.b,而不做一些醜陋的類型轉換。另外,在你的編輯中,我不確定我是否理解爲什麼構造函數模式沒有被粘貼。是因爲不適用? –

+0

說實話,我不知道它爲什麼起作用。我通過反覆試驗偶然發現了它。這絕對是在Scala規範中的某處提到的。如果它與您的案例相關,您可能想查看它。 – agilesteel

+1

是的,您在case語句中使用的模式是由unapply函數的結果給出的模式。它永遠不會被咖喱。 scala規範中的相應部分是§8.1.8 – Nicolas

2

您可以使用普通的案例類,只需定義一個具有多個參數列表的工廠方法。

+0

可能我們可以補充一點,如果工廠方法在伴隨對象中聲明,就不能使用'apply'進行升級(因爲它會和第其中一個表示感謝案例分類)。 – Nicolas

11

如果你看一下B類創建不應用功能的簽名,你會看到,它是:unapply(x$0: Q): Option[Int]。因此,unapply函數可以處理案例類的第一個參數範圍。

它由階規範(第5.3.2節)證實:

的情況下類 的第一個參數部分形式參數被稱爲元素;他們被特別對待。首先, 這個參數的值可以作爲構造函數模式的字段提取出來。

它聲稱只有第一個參數部分可通過提取器。

幾種解決方法:

  • uncurry您的參數
  • ,如果你要測試的2個值使用帶保護與模式匹配:case [email protected](3) if x.b == "bazinga" => ...
  • 使用一個普通的類,並定義自己的伴侶對象的自己申請/不申請