2012-08-16 17 views
17

ich die folgende Klassenhierarchie:Scala - ein Tupel von verwandten Arten Mustervergleich

class A 
class B extends A 
class C extends A 

dann, eine andere Klasse ist die Instanzen dieser Klassen nimmt und gibt es ein Verfahren, bei dem zwei Fälle von pattern-Matching möglich ist wie folgt aus:

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

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

wenn es jedoch sollte die Anpassung für den zweiten Fall (B, C) lösen, versucht er es als (B, B) Lösung und kommt, dass C cannot be cast to B mit der Klasse Guss Ausnahme auf. Warum? Was ist zu tun? Wie kann ich das umgehen?

Antwort

26

Ihre Syntax ist nicht ganz richtig (kompiliert nicht). obwohl

Dies funktioniert:

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

Ich habe so lange gekämpft, um die richtige Syntax herauszufinden ... Danke! – Benoit

2

Ich habe diesen Code funktioniert.
Zuerst habe ich einen Fall zu Ihrer Klassendefinition hinzugefügt.

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

Zweitens änderte ich den 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") 
    } 
    } 
} 

Nun, was ich habe:

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

Die case ein Verfahren anzuwenden und ein Unapply hinzufügt.

+0

Ja, Fall Klassen ... aber sie haben Fehler mit Vererbung .. Ich werde sehr glücklich sein, wenn sie das irgendwann beheben ... – noncom

+0

Ich bin komplett mit dir. –

+1

Dieser Code wird im modernen Scala nicht kompiliert, da die Case-Vererbung seit 2.9 nicht mehr möglich ist. @noncom Dies ist kein Fehler, dies ist per Entwurf –

7

Das Problem, wie immer, ist Typ gelöscht. (B,C) ist syntaktischer Zucker für Tuple2[B,C], der zur Laufzeit auf Tuple2 gelöscht wird. Die case-Anweisung überprüft, dass (B,C) mit Tuple2 übereinstimmt, schlägt dann jedoch fehl.

In Ihrem Fall wäre die einfachste Lösung entsprechen gegen ‚eins‘ und ‚zwei‘ einzeln, anstatt sie in einem Tupel Einwickeln:

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

Es ist nicht so schön, aber es wird nicht leiden unter den gleichen Problemen.

Edit: Eigentlich würde ich mit Brian Smiths Lösung gehen - passend innerhalb des Tupels anstatt außerhalb. Es vermeidet das Problem in ähnlicher Weise, sieht aber schöner aus.

Verwandte Themen