title: Is it good practice to make case classes sealed?
body: <p>The main reason to seal classes seems to be that this allows the compiler to do exthaustivity searches when pattern matching on those classes. Say I have data types meant for pattern matching. Toy example:</p>
  
  <pre><code>sealed trait Statement
  case class Assign(name: String, value: Int) extends Statement
  case class Print(name: String) extends Statement
  case class IfZero(name: String, thenn: Statement, els: Option[Statement]) extends Statement
  case class Block(statements: List[Statement]) extends Statement
  </code></pre>
  
  <p>The use case for these classes would be to consume them through pattern matching:</p>
  
  <pre><code>def execute(statement: Statement): Unit = statement match {
      case Assign(name, value)      =&gt; ???
      case Print(name)              =&gt; ???
      case IfZero(name, thenn, els) =&gt; ???
      case Block(statements)        =&gt; statements foreach { execute(_) }
    }
  </code></pre>
  
  <p>To this end, the <code>Statement</code> trait is <code>sealed</code> so that the compiler can warn me if I forget one statement kind in the match statement. But what about the case classes? Case classes cannot inherit from each other, but traits and ordinary classes can. So, is it good practice to seal the case classes as well? What could go wrong if I don't?</p>