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}")
}
我什么时候应该用一个来反对另一个,为什么。
当涉及到case类时,两者可以互换使用。
如果您更喜欢引用匹配的ExternalUser
值本身,那么第一种方法更有意义,因为您可以通过u
引用它。
如果您喜欢将整个case类分解为多个部分(标记、电子邮件等(,那么第二种方法更有意义,因为您不必一直通过u
来选择它们。
如果你喜欢使用第二种方法,但你仍然想引用整个案例类,你也可以这样做:
case u @ InternalUser(tag, email) =>
println(s"$u $tag $email")
它们非常相似。第二种形式允许您进行递归模式匹配,因此您不仅可以绑定变量名,还可以进一步解构这些部分:
val G = "(.*)@gmail.com".r
user match {
case InternalUser(tag, G(localPart)) =>
// handle internal users with Gmail address here
...
}
第一种形式的优点是不需要列出所有字段。这对于具有许多与此上下文无关的字段的事例类非常有用,或者如果您希望事例类将来获得额外的字段,则不必更改此match
表达式。
ExternalUser
可以是trait
、class
或case class
。成员元素name
可以是具有该名称的任何公开可用的元素。它不一定是构造函数参数。
InternalUser(a,b)
必须有自己的unapply()
方法,case class
会自动提供该方法。在这种情况下,unapply()
方法将填充本地标识符a
和b
。如果unapply()
方法是由case class
提供的默认方法,则本地标识符将与case class
构造函数参数具有1对1的对应关系。