【Java学習|豆知識】Java 17以降の強力な武器!sealedクラスで継承を賢く制御しよう

1. 導入:なぜsealedクラスが重要なのか

Javaの開発現場において、継承(Inheritance)は強力なツールですが、不用意にクラスを公開すると「誰がどこで継承しているか分からない」という保守性の低下を招きます。特にドメインモデルの定義において、「特定の型しか存在しないこと」を保証したい場面は多々あります。
Java 17から正式導入されたsealed修飾子は、継承可能なクラスを開発者が明示的に制限するための仕組みです。これにより、意図しない拡張を防ぎ、コンパイラによる網羅性チェックを可能にするため、コードの堅牢性が劇的に向上します。

2. 基礎知識:sealed修飾子とは

sealedクラスは、どのクラスがそのクラスを継承できるかを許可(permits)する仕組みです。
sealed:継承元となるクラスを制限します。
permits:継承を許可するクラスを列挙します。
non-sealed:sealedの制限を解除し、誰でも継承できるようにします。
final:これ以上継承させないことを明示します。

この仕組みにより、switch式などと組み合わせる際、コンパイラが「すべてのサブクラスを網羅しているか」をチェックできるようになります。これは、型の網羅性を担保する上で極めて強力です。

3. 実装/解決策:sealedクラスとswitch式の活用

sealedクラスを定義し、それをswitch式で処理する際、Javaコンパイラはすべての可能性がカバーされているかを判断します。もし、新しいサブクラスを追加したのにswitch式で処理し忘れると、コンパイルエラーになるため、バグを未然に防ぐことができます。

4. サンプルプログラム

以下のコードは、図形を表現するクラス体系です。矩形(Rectangle)と円(Circle)のみを許可し、それらを計算するロジックを実装しています。


// sealed修飾子で継承先を制限する
public sealed interface Shape permits Rectangle, Circle {
double calculateArea();
}

// 許可されたサブクラスはfinalまたはsealed、あるいはnon-sealedである必要がある
public final class Rectangle implements Shape {
private final double width, height;
public Rectangle(double w, double h) { this.width = w; this.height = h; }
public double calculateArea() { return width height; }
}

public final class Circle implements Shape {
private final double radius;
public Circle(double r) { this.radius = r; }
public double calculateArea() { return Math.PI radius radius; }
}

// switch式での利用例
public class ShapeCalculator {
public static void printArea(Shape shape) {
// コンパイラがShapeのサブクラスを全て網羅しているかチェックしてくれる
double area = switch (shape) {
case Rectangle r -> r.calculateArea();
case Circle c -> c.calculateArea();
// sealedのおかげでdefault句が不要になる(網羅性が保証されているため)
};
System.out.println("面積: " + area);
}
}

5. 応用・注意点:現場での活用ポイント

網羅性チェックのメリット
従来のif-elseやswitch文では、新しいクラスを追加した際に処理を書き忘れるリスクがありました。sealedクラスとswitch式を組み合わせれば、コンパイルエラーとして検知できるため、開発者の修正漏れを確実に防げます。

注意点
モジュール境界:sealedクラスのpermitsで指定するクラスは、同一モジュール(または同一パッケージ)内に配置する必要があります。
設計のトレードオフ:継承を制限するということは、将来的な拡張性が限定されることを意味します。むやみに全てをsealedにするのではなく、ビジネスロジック上で「この型はこれ以上増えない」と確定しているドメインモデルに対して適用するのが、シニアエンジニアとしての賢い使い分けです。

ぜひ、次回の開発からsealed修飾子を活用して、堅牢なクラス設計を実践してみてください。

コメント

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