Scala: Sealed classes
Whenever you write a pattern match, you need to make sure you have covered all of the possible cases. Sometimes you can do this by adding a default case at the end of the match, but that only applies if there is a sensible default behavior. What do you do if there is no default? How can you ever feel safe that you covered all the cases?
Scala compiler can help here. For that make the superclass of your case classes sealed. A sealed class cannot have any new subclasses added except the ones in the same file. This is very useful for pattern matching because it means you only need to worry about the subclasses you already know about. What's more, you get better compiler support as well. If you match against case classes that inherit from a sealed class, the compiler will flag missing combinations of patterns with a warning message.
sealed abstract class Expr case class Var(name: String) extends Expr case class Number(num: Double) extends Expr case class UnOp(operator: String, arg: Expr) extends Expr case class BinOp(operator: String, left: Expr, right: Expr) extends Expr Listing 15.16 - A sealed hierarchy of case classes. Now define a pattern match where some of the possible cases are left out: def describe(e: Expr): String = e match { case Number(_) => "a number" case Var(_) => "a variable" } You will get a compiler warning like the following: warning: match is not exhaustive! missing combination UnOp missing combination BinOp Such a warning tells you that there's a risk your code might produce a MatchError exception because some possible patterns (UnOp, BinOp) are not handled.
If you sure that there won't be other case happen then you can shut compiler warning by using @unchecked annotation:
def describe(e: Expr): String = (e: @unchecked) match { case Number(_) => "a number" case Var(_) => "a variable" }
The Option type:
Scala has a standard type named Option for optional values. Such a value can be of two forms: Some(x), where x is the actual value, or the None object, which represents a missing value.
Scala encourages the use of Option to indicate an optional value. By this approach it is obvious to readers of code that a variable whose type is Option[String] is an optional String than a variable of type String, which may sometimes be null.
def show(x: Option[String]) = x match { case Some(s) => s case None => "?" }