takafumi blog

日々の勉強メモ

【Scala】 sealedとパターンマッチ

環境   Scala 2.11.8

シールドクラス(トレイト)を継承したサブクラスは、すべて同一のソースファイルに定義される。
そしてシールドクラスをパターンマッチに使用されると、match式の網羅性をコンパイラがチェックできる。

sealedなし

このときはcaseのパターンが全て網羅されなくてもエラーは出ない。
が当然、網羅されていないパターンを投げると実行時エラーになる

trait Msg

case class TxtMsg() extends Msg
case class ObjMsg() extends Msg
case class ErrMsg() extends Msg

object Msg {
  def message(m: Msg): Unit = m match {
    case TxtMsg() => println("Text")
  }
}
$ scalac Msg.scala
$ # エラーは出ない
scala> :load Msg.scala
Loading test.scala...
defined trait Msg
defined class TxtMsg
defined class ObjMsg
defined class ErrMsg
defined object Msg

scala> Msg.message(ErrMsg())
scala.MatchError: ErrMsg() (of class ErrMsg)
  at Msg$.message(<console>:16)
  ... 33 elided

sealedあり

こうすると、コンパイルエラーになるので安全。

sealed trait Msg

case class TxtMsg() extends Msg
case class ObjMsg() extends Msg
case class ErrMsg() extends Msg

object Msg {
  def message(m: Msg): Unit = m match {
    case TxtMsg() => println("Text")
    case ObjMsg() => println("Text")
    // case ErrMsg() => println("Text")
  }
}
$ scalac test.scala
test.scala:8: warning: match may not be exhaustive.
It would fail on the following input: ErrMsg()
  def message(m: Msg): Unit = m match {
                              ^
one warning found