2013-03-27 3 views
48

Ich frage mich, wie kann ich mehrere Muster Mustererkennung verwenden. Ich habe:Scala mehrere Muster entsprechen

abstract class MyAbstract 

case class MyFirst extends MyAbstract 
case class MySecond extends MyAbstract 
case class MyThird extends MyAbstract // shouldn't be matched and shouldn't call doSomething() 

val x: MyAbstract = MyFirst 

x match { 
case a: MyFirst => doSomething() 
case b: MySecond => doSomething() 
case _ => doSomethingElse() 
} 

So möchte ich etwas schreiben:

x match { 
case a @ (MyFirst | MySecond) => doSomething() 
case _ => doSomethingElse() 
} 

ich ähnliche Konstruktion in einigen Tutorial sah, aber es gibt mir eine Fehlermeldung:

pattern type is incompatible with expected type; 
[error] found : object MyFirst 
[error] required: MyAbstract 

So ist gibt es eine Möglichkeit, einige verschiedene Typen in der case-Klausel zu definieren? Ich denke, es würde Code hübscher machen. Als ob ich 5 davon haben würde, werde ich den gleichen Code 5 Mal schreiben (doSomething() aufrufen).

Vielen Dank im Voraus!

+0

Ich denke, es ist ein XY-Problem; Sie haben eine gemeinsame Oberklasse für alle "doSomething" -Fälle, warum passen Sie die "case a: MyAbstract" dann nicht ...? –

+0

Sorry, vergessen zu erwähnen, dass ich andere Klassen habe, die die MyAbstract-Klasse erweitern und DoSomething nicht aufrufen sollten. – psisoyev

+0

Oh, OK, ich wollte das nur klarstellen :) Du hast jetzt eine korrekte Antwort auf dein Problem. –

Antwort

93

Ihnen fehlen die Klammern für Ihre Fallklassen. Fallklassen ohne Parameterlisten sind veraltet.

Versuchen Sie folgendes:

abstract class MyAbstract 
case class MyFirst() extends MyAbstract 
case class MySecond() extends MyAbstract 

val x: MyAbstract = MyFirst() 


x match { 
    case aOrB @ (MyFirst() | MySecond()) => doSomething(aOrB) 
    case _ => doSomethingElse() 
} 

Wenn Sie für Ihren Fall Klassen zu viele params haben und mögen es nicht lange Foo(_,_,..) Muster zu schreiben, dann vielleicht:

x match { 
    case aOrB @ (_:MyFirst | _:MySecond) => doSomething(aOrB) 
    case _ => doSomethingElse() 
} 

Oder einfach:

x match { 
    case _:MyFirst | _:MySecond => doSomething(x) // just use x instead of aOrB 
    case _ => doSomethingElse(x) 
} 

Aber vielleicht wollten Sie nur Singleton Case Objekte?

abstract class MyAbstract 
case object MyFirst extends MyAbstract 
case object MySecond extends MyAbstract 

val x: MyAbstract = MyFirst 

x match { 
    case aOrB @ (MyFirst | MySecond) => doSomething() 
    case _ => doSomethingElse() 
} 
+0

Und es gibt keine Möglichkeit, Klammern zu vermeiden? Da ich ein paar Parameter habe und es hässlich wird: Fall a @ (MyFirst (_, _, _, _, _) | MySecond (_, _, _, _, _)) => doSomething() – psisoyev

+5

Hast du Miss 'obj @ (_: MyFirst | _: MySecond) '? –

+0

Ich brauche 'obj' in Fällen, wo ich es in' DoSomething' Aufruf verwende. In meinem Fall verwendete der Aufruf von "doSomething" nicht "obj", also brauche ich ihn nicht. Aber trotzdem, danke für deinen Kommentar! – psisoyev