Pattern matching is matching the value with given cases. It is much more powerful in scala as it allows us to match a value with classes and does the destruct of the value for us.

For instance,

sealed trait Notification
 
case class Email(from: String, to: String, body: String) extends Notification
case class VoiceMail(from: String, to: String, body: String) extends Notification
 
 
def printMessage(notification: Notification): Unit = notification match
  case Email(from, to, body) => println(s"You've got message from ${from} with message \"${body}\"")
  case VoiceMail(from, to, body) => println(s"You've got voice mail from ${from} with message \"${body}\"")
 
 
 
printMessage(Email("nitin", "hemant", "Hey! There"))
printMessage(VoiceMail("nitin", "hemant", "Hey! There"))

Pattern guard

It is also possible to add an extra condition with case expression to make the matching more specific.

x match
  case matchValue booleanExpression => ...
  ...

Matching on Types

Sometimes we want to invoke a method on a matching type, we can’t just do, case Email() => ...

def deleteNotification(notification: Notification): Unit = notification match
  case e: Email => e.delete
  case e: VoiceMail => e.delete
  case _ => println("INVALID")

Match expression Exhaustive

Notification case class is sealed which gives the advantage of match expression giving the warning when all the subtypes of sealed class are not provided as cases.

For instance,

def deleteNotification(notification: Notification): Unit = notification match
  case e: Email => e.delete

Compiler gives the warning,

1 |def deleteNotification(notification: Notification): Unit = notification match
  |                                                           ^^^^^^^^^^^^
  |                         match may not be exhaustive.
  |
  |                         It would fail on pattern case: VoiceMail(_, _, _)