ChatGPT解决这个技术问题 Extra ChatGPT

Scala multiple type pattern matching

I'm wondering how can I use multiple type pattern matching. I have:

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 I'd like to write something like:

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

I saw similar construction in some tutorial, but it gives me error:

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

So is there a way to define few different types in on case clause? I think it would make code prettier. As if I will have 5 of them, I will write same code 5 times (calling doSomething()).

Thanks in advance!

I think it's a XY-problem; you have a common superclass for all doSomething cases, why not match the case a : MyAbstract then...?
Sorry, forgot to mention, that I have other classes, that extend MyAbstract class and shouldn't call doSomething.
Oh, OK, just wanted to clarify that :) You have a correct answer to your problem now though.

F
Faiz

You are missing the parenthesis for your case classes. Case classes without parameter lists are deprecated.

Try this:

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

If you have too many params for your case classes and don't like having to write long Foo(_,_,..) patterns, then maybe:

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

Or just:

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

But perhaps you just wanted singleton case objects?

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

And there is no way to avoid parenthesis? As I have a few parameters and it becomes ugly: case a @ (MyFirst(, _, _, _, _) | MySecond(, _, _, _, _)) => doSomething()
Did you miss obj @ (_: MyFirst | _: MySecond)?
I need obj in cases, where I'm using it in doSomething call. In my case, the call of doSomething wasn't using obj, so I don't need it. But anyway, thanks for your comment!
@Jean-PhilippePellet Indeed I have. Let me edit my post to add it.
It would be nice if the compile was smart enough to find the closest common type instead of defaulting to the input type.