Question

I have a super class Command, many different subclasses extend from Command and at the same time may also extend one or more of these traits ValuesCommand, KeysCommand, MembersCommand and many others.

Now I want to pattern match all implementations of Command that extend a ValuesCommand and KeysCommand at the same time.

Here is some pseudocode of what I want to achieve:

def apply(cmd : Command) = {
  cmd match {
    case c:(ValuesCommand && KeysCommand) => c.doSomething()
  }
}

I could fallback to match the first trait and nest a second match. But I don't really need it and looks terrible.

Was it helpful?

Solution

You can do it like this:

def apply(cmd : Command) = {
  cmd match {
    case c: ValuesCommand with KeysCommand => c.doSomething()
  }
}

When you have a class (e.g ValKey here) that both extends ValuesCommand and KeysCommand you also have something like

class ValKey extends ValuesCommand with KeysCommand`

Edit (Your comment):

I can't imagine a scenario where you want something like ValuesCommand or KeysCommand in this case. You can read the link in @Randall Schulz comment to see how to get an OR.

Let's imagine you have your OR (v), like described in the link.

case c: ValuesCommand v KeysCommand => //soo.. what is c?

Now you still have to pattern-match on c to find out what kind of command it is. (most likely)

So in the end you can still do it directly like this:

cmd match {
  case vc: ValuesCommand => vc.doSomething()
  case kc: KeysCommand   => kc.doSomehtingElse()
}

Edit2:

For a scenario where you want to call your accept method on cmd, only if it is a ValuesCommand or KeysCommand, you can do:

cmd match {
  case _: ValuesCommand | _: KeysCommand => accept(cmd)
}

which, i guess, is more DRY than

cmd match {
  case vc: ValuesCommand => accept(cmd)
  case kc: KeysCommand   => accept(cmd)
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top