Search code examples
scalatypespattern-matching

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


Solution

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