Jabir Minjibir
Jabir Minjibir

Reputation: 137

What is the difference between this two following cases of pattern matching in scala

sealed trait User
case class ExternalUser(name: String, email: String) extends User
case class InternalUser(tag: String, email: String) extends User

val user: User = ...

user match {
  case u: ExternalUser => 
    println(s"${u.name}")

  case InternalUser(tag, email) => 
    println(s"${tag}")
}

When should I use one as oppose to the other and why.

Upvotes: 2

Views: 81

Answers (3)

slouc
slouc

Reputation: 9698

When it comes to case classes, both can be used interchangeably.

If you prefer to have a reference to the matched ExternalUser value itself, then first approach makes more sense, because you can refer to it via u.

If you prefer to unapply the whole case class into its parts (tag, email etc.), then second approach makes more sense, because you don't have to keep selecting them via u.

If you prefer to use the second approach, but you still want to hold a reference to the whole case class, you can also do:

case u @ InternalUser(tag, email) => 
  println(s"$u $tag $email")

Upvotes: 8

Matthias Berndt
Matthias Berndt

Reputation: 4587

They're quite similar. The second form allows you to do recursive pattern matching, so instead of just binding variable names you can also deconstruct the parts further:

val G = "(.*)@gmail.com".r
user match {
  case InternalUser(tag, G(localPart)) =>
    // handle internal users with Gmail address here
  ...
}

The first form has the advantage that you don't need to list all the fields. This is useful for case classes with many fields that aren't relevant in this context, or if you expect the case class to gain additional fields in the future – you then don't have to change this match expression to go along with it.

Upvotes: 3

jwvh
jwvh

Reputation: 51271

ExternalUser can be a trait, class, or case class. The member element name can be any publicly available element by that name. It doesn't have to be a constructor argument.

InternalUser(a,b) must have it's own unapply() method, which a case class automatically supplies. The unapply() method will populate the local identifiers, a and b in this case. If the unapply() method is the default supplied by the case class then the local identifiers will have a 1-to-1 correspondence with the case class constructor arguments.

Upvotes: 1

Related Questions