【Java学習|実務向け】Javaの堅牢性を高めるsealed classesと網羅的なパターンマッチングの活用術

導入

大規模なJavaアプリケーション開発において、「継承関係の制御」と「網羅的な分岐処理」はバグを未然に防ぐための重要な鍵です。従来のJavaでは、クラスの継承を完全に制限することが難しく、if-elseやswitch文による分岐で意図しないサブクラスが混入するリスクがありました。Java 17で正式導入されたsealed classes(シールクラス)は、継承可能なクラスを明示的に指定することで、ドメインモデルの安全性を劇的に向上させます。本記事では、sealed classesとモダンなswitch式を組み合わせて、堅牢な制御フローを実装する方法を解説します。

基礎知識

sealed classesとは、そのクラスを継承(または実装)できるクラスを、開発者が明示的に制限するための仕組みです。

  • sealed: 継承可能なサブクラスを許可するクラス。
  • permits: 継承を許可するクラスを列挙するキーワード。
  • non-sealed / final: 許可されたサブクラス側で、さらに継承を継続させるか(non-sealed)、末端とするか(final)を定義します。

この仕組みにより、コンパイラは「サブクラスが何であるか」を完全に把握できるため、switch式において網羅性チェックが可能になります。

実装/解決策

sealed classesを導入する際は、以下のステップで実装します。
1. 親クラスにsealed修飾子を付与し、permitsでサブクラスを列挙する。
2. サブクラス側でfinal修飾子を付与し、これ以上継承させないことを明示する。
3. switch式を使い、全サブクラスに対する処理を記述する。この際、default句を書かなくてもコンパイラが網羅性を保証してくれます。

サンプルプログラム

以下は、決済処理を例にした実用的なサンプルコードです。


// 決済の型を限定するsealedインターフェース
public sealed interface PaymentMethod permits CreditCard, PayPal, BankTransfer {
}

// 各サブクラスはfinalを付与して継承を終了させる
public final record CreditCard(String cardNumber) implements PaymentMethod {}
public final record PayPal(String email) implements PaymentMethod {}
public final record BankTransfer(String accountId) implements PaymentMethod {}

public class PaymentProcessor {
public String process(PaymentMethod method) {
// switch式による網羅的な分岐
// 許可された全型をカバーしているため、default句は不要
return switch (method) {
case CreditCard c -> "クレジットカード[" + c.cardNumber() + "]で決済中";
case PayPal p -> "PayPal[" + p.email() + "]で決済中";
case BankTransfer b -> "銀行振込[" + b.accountId() + "]で決済中";
// ここで新しいサブクラスを追加しても、コンパイラがエラーで教えてくれる
};
}
}

応用・注意点

現場で活用する際のポイントを3点挙げます。

1. 網羅性の恩恵: sealed classesの最大の利点は、将来的にサブクラスを追加した際に、switch式で処理が漏れている箇所をコンパイルエラーとして即座に検知できる点です。これにより、修正漏れによるランタイムエラーを激減させることができます。
2. レコードとの併用: サンプルでも示した通り、record型とsealed classesの相性は抜群です。データ保持を目的とした型であれば、recordを使うことでボイラープレートコードを大幅に削減できます。
3. 設計の制約: sealed classesは強力ですが、継承関係を厳格に固定するため、ライブラリ開発などで「利用者が自由にサブクラスを拡張したい」というケースには向きません。あくまで、特定のビジネスロジック内での閉じたドメインモデルに適用するのがベストプラクティスです。

適切にsealed classesを使いこなすことで、複雑な条件分岐のコードを整理し、保守性の高い堅牢なシステムを構築してください。

コメント

タイトルとURLをコピーしました