2012-08-16 79 views
17

我有下面的類層次結構的元組:斯卡拉 - 模式匹配相關類型

class A 
class B extends A 
class C extends A 

然後,有另一類這需要這些類的實例,有一個方法,其中,2箱子模式匹配有可能是這樣的:

class D (one: A, two: A) { 

    def work { 
    (one, two) match { 
     case (o, t): (B, B) => ... blablabla 
     case (o, t): (B, C) => ... blablabla 
     case _ => 
    } 
    } 
} 

然而,當它應該贊成第二種情況下(B, C)的解決匹配,它試圖解決它(B, B)並用類轉換異常是C cannot be cast to B出現。爲什麼?該怎麼辦?我怎樣才能解決這個問題?

回答

26

你的語法不太對(不編譯)。

這工作雖然:

object Matcher extends App { 

    class A 
    class B extends A 
    class C extends A 

    class D(one: A, two: A) { 

    def work { 
     (one, two) match { 
     case (o: B, t: B) => println("B") 
     case (o: B, t: C) => println("C") 
     case _ => 
     } 
    } 
    } 

    val d1 = new D(new B, new B) 
    val d2 = new D(new B, new C) 

    d1.work 
    //B 
    d2.work 
    //C 
} 
+0

我一直在努力尋找正確的語法......謝謝! – Benoit 2014-02-27 09:58:43

2

我使這個代碼工作。
首先我給你的類定義添加了一個case。

case class A 
case class B extends A 
case class C extends A 

其次我改變了work

class D(one: A, two: A) { 
    def work { 
    (one, two) match { 
     case (o: B, t: B) => println("BB") 
     case (o: B, t: C) => println("BC") 
     case (o: C, t: C) => println("CC") 
     case _ => println("AA") 
    } 
    } 
} 

現在我得到了什麼:

new D(B(),B()).work  => BB 
new D(B(),C()).work  => BC 
new D(C(),C()).work  => CC 
new D(A(),B()).work  => AA 

case增加了應用和不應用方法。

+0

是的,案例類...但他們有繼承錯誤..我會很高興,如果他們修復某個時候... – noncom 2012-08-16 12:35:46

+0

我完全和你在一起。 – 2012-08-16 12:46:34

+1

這段代碼不會在現代Scala中編譯,因爲我認爲從2.9開始禁止案例繼承。 @noncom這不是一個bug,這是由設計 – 2012-08-16 21:51:16

7

的問題,一如既往,被刪除的類型。 (B,C)是語法糖Tuple2[B,C],它在運行時擦除到Tuple2。案例陳述驗證(B,C)Tuple2匹配,但是未能投射它。

在你的情況,最簡單的解決辦法是要匹配的「一」和「二」單獨,而不是在一個元組包裹其中:

one match { 
    case o : B => two match { 
    case p : C => ... 
    case p : B => ... 
    } 
    ... 
} 

這不是那麼漂亮,但它不會遭受同樣的問題。

編輯:其實,我會與布賴恩史密斯的解決方案 - 匹配內部元組而不是外部。它以類似的方式避免了這個問題,但看起來更好。