Scala Multiple Type Pattern Matching


79

Ich frage mich, wie ich mehrere Mustermuster verwenden kann. Ich habe:

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()
}

Also möchte ich etwas schreiben wie:

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

Ich habe in einem Tutorial eine ähnliche Konstruktion gesehen, aber es gibt mir einen Fehler:

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

Gibt es also eine Möglichkeit, in der case-Klausel einige verschiedene Typen zu definieren? Ich denke, das würde den Code schöner machen. Als ob ich 5 davon hätte, schreibe ich 5 Mal denselben Code (rufe doSomething () auf).

Danke im Voraus!


Ich denke, es ist ein XY-Problem. Sie haben eine gemeinsame Superklasse für alle doSomethingFälle, warum nicht die case a : MyAbstractdann ...?
Patryk Ćwiek

Entschuldigung, ich habe vergessen zu erwähnen, dass ich andere Klassen habe, die die MyAbstract-Klasse erweitern und doSomething nicht aufrufen sollten.
Psisoyev

Oh, OK, wollte das nur klarstellen :) Sie haben jetzt aber eine richtige Antwort auf Ihr Problem.
Patryk Ćwiek

Antworten:


134

Ihnen fehlt die Klammer für Ihre Fallklassen. Fallklassen ohne Parameterlisten sind veraltet.

Versuche dies:

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 zu viele Parameter für Ihre Fallklassen haben und keine langen Foo(_,_,..)Muster schreiben möchten , dann vielleicht:

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

Oder nur:

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

Aber vielleicht wollten Sie nur Einzelfallobjekte?

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()
}

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

9
Haben Sie vermissen obj @ (_: MyFirst | _: MySecond)?
Jean-Philippe Pellet

Ich brauche objin Fällen, in denen ich es im doSomethingAnruf benutze . In meinem Fall wurde der Anruf von doSomethingnicht verwendet obj, daher brauche ich ihn nicht. Trotzdem danke für deinen Kommentar!
Psisoyev

@ Jean-PhilippePellet In der Tat habe ich. Lassen Sie mich meinen Beitrag bearbeiten, um ihn hinzuzufügen.
Faiz

1
Es wäre schön, wenn die Kompilierung intelligent genug wäre, um den nächstgelegenen gemeinsamen Typ zu finden, anstatt standardmäßig den Eingabetyp zu verwenden.
Nilskp
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.