ケースクラスとの連携

Scalaにおけるパターンマッチングは、**ケースクラス(case class)**と非常に密接に連携して機能します。ケースクラスは、パターンマッチングを行う上で特に便利な機能を備えており、構文を簡潔かつ明瞭に保つ役割を果たします。


ケースクラスとパターンマッチングの連携の概要

ケースクラスの特徴

ケースクラスには以下のような特徴があり、これがパターンマッチングとの親和性を高めています。

  • 自動的に apply メソッドと unapply メソッドを持つ(後者がパターンマッチングに関係)

  • コンストラクタの引数が自動的に val として定義される

  • toStringequalshashCode などが自動実装される

これにより、値の構造に基づいた分岐処理が非常に直感的に書けます。


例:ケースクラスとパターンマッチングの使用

scala
// ケースクラスの定義 sealed trait Expr case class Number(value: Int) extends Expr case class Sum(left: Expr, right: Expr) extends Expr // パターンマッチングの使用例 def eval(expr: Expr): Int = expr match { case Number(value) => value case Sum(l, r) => eval(l) + eval(r) }

解説

  • Expr は共通の親トレイト(sealed trait)で、これはすべての継承元がこのファイル内にあることを示します(パターンマッチングの網羅性チェックを有効にするため)。

  • NumberSumExpr を継承するケースクラスです。

  • match 式では、Number(value)Sum(l, r) のように、インスタンスの構造を分解してそれぞれの値を変数に束縛できます。

  • これは unapply メソッドによるパターンの分解が内部で行われているためです。


ケースクラスがパターンマッチングに向いている理由

  1. 構造的な比較が簡単にできる
    パターンに合致するかどうかを、手続き的なコードを書くことなく記述可能。

  2. データの分解が自然に行える
    case Number(value) のように、インスタンスから値を直接取り出せる。

  3. 網羅性チェック(Exhaustiveness Check)が有効になる
    sealed traitsealed abstract class と組み合わせることで、すべてのパターンが網羅されているかコンパイル時に検査される。


応用:ネストされたパターンマッチング

scala
val expr = Sum(Number(1), Sum(Number(2), Number(3))) val result = expr match { case Sum(Number(a), Sum(Number(b), Number(c))) => a + b + c case _ => 0 }

このように、ネストされた構造も簡単に扱えるのがケースクラスとパターンマッチングの大きな利点です。


まとめ

Scalaにおいて、ケースクラスとパターンマッチングはセットで使われることが多く、以下のような利点があります。

  • 簡潔で明瞭な構文で構造を分解できる

  • 型安全かつ網羅性チェックが可能

  • ネストされた構造も扱いやすい

これにより、抽象構文木(AST)の操作データの分類・分岐処理などに非常に有効な手段となっています。

生成日:2025/05/04