Javaのsealedクラス(シール・クラス)とは?継承を制御する新機能をやさしく解説
生徒
「最近Javaのsealedクラスって聞いたんですけど、それって何ですか?」
先生
「sealedクラスはJava17から導入された新しい機能で、継承できるクラスを制限できるものなんだよ。」
生徒
「継承を制限?どうしてそんなことをするんですか?」
先生
「それは、セキュリティや設計の意図を明確にするためなんだ。詳しく見ていこう!」
1. sealedクラス(シール・クラス)とは何か?
Javaのsealedクラスは、特定のクラスやインターフェースだけが継承できるように制限をかけるための新しい修飾子です。Java17で正式に追加されたこの機能は、オブジェクト指向の設計をより安全かつ明確に保つために役立ちます。
sealedクラスを使うと、「このクラスを継承していいのは、AとBだけ」と明示的に宣言できます。
2. sealedクラスの基本構文
sealedクラスは、クラス定義の際にsealedキーワードを使い、どのクラスが継承できるかをpermitsで明示します。
public sealed class Animal permits Dog, Cat {
}
この例では、DogクラスとCatクラスのみがAnimalを継承できます。
3. permits句で指定されたクラスの条件
permitsで指定するサブクラスは、同じファイル内にあるか、コンパイラが確認できる必要があります。そして、指定されたクラスは次の3種類のいずれかの修飾子を付ける必要があります:
- sealed: さらに限定的な継承を許可する
- non-sealed: 制限を解除し、誰でも継承できるようにする
- final: そのクラスで継承を完全に禁止する
4. sealedクラスの継承パターン例
public sealed class Animal permits Dog, Cat {
}
public final class Dog extends Animal {
}
public non-sealed class Cat extends Animal {
}
Dogはfinalなので、誰も継承できません。一方Catはnon-sealedなので、Catを継承することは誰でも可能です。
5. sealedインターフェースの使い方
sealedはクラスだけでなく、インターフェースにも使うことができます。
public sealed interface Shape permits Circle, Rectangle {
}
public final class Circle implements Shape {
}
public final class Rectangle implements Shape {
}
インターフェースでも、同様にpermitsで実装できるクラスを制限します。
6. sealedクラスを使うメリットとは?
Javaでsealedクラスを使う主なメリットは、以下のような点にあります。
- クラス階層の設計意図を明確にできる
- 予期しない継承を防げる
- セキュリティリスクの低減
- IDEによるコード補完や警告がより適切になる
これにより、保守性の高いコードを書くことが可能になります。
7. sealedクラスと密接な関係にあるfinal・non-sealedとは?
sealed修飾子と一緒に覚えておきたいのが、finalとnon-sealedです。
finalは、クラスの継承を完全に止める修飾子です。sealedな親から継承し、それ以上の継承を禁止したいときに使います。
non-sealedは、逆に継承の制限を取り除くものです。親がsealedでも、子がnon-sealedであれば、そのクラスをさらに継承可能になります。
8. sealedクラスを使用する上での注意点
sealedクラスを使う際には、以下の点に注意しましょう。
- 継承可能なクラスをすべて
permitsで明示する必要がある - すべてのサブクラスはsealed・non-sealed・finalのいずれかを指定しなければならない
- Java17以降でないと使用できない(--enable-previewは不要)
- sealedクラスとインターフェースはパッケージ設計と相性が良い
9. sealedクラスの応用例:状態管理やドメインモデルに活用
sealedクラスは、状態を表現するクラス階層にもよく使われます。例えば、処理の状態(成功・失敗・保留など)を表すときに使うと便利です。
public sealed interface Result permits Success, Failure {
}
public final class Success implements Result {
}
public final class Failure implements Result {
}
このように、設計上許可されたクラスだけを使うことで、コードの安全性や予測可能性が格段に上がります。
10. sealedクラスを取り入れるタイミングとは?
sealedクラスは、以下のような場面で特に有効です。
- 制限された状態やイベントなどを明確にしたいとき
- ドメイン駆動設計(DDD)でモデルの厳格な定義が必要なとき
- セキュアなAPI設計を意識するとき
Javaで継承の自由度を持たせつつも、制御をしっかりしたいときにsealedクラスはとても有効な手段です。
まとめ
Javaのsealedクラスで安全な継承設計を実現しよう
Javaのsealedクラス(シール・クラス)は、Java17から導入された強力な継承制御機能です。クラスやインターフェースの継承を限定し、明示的に許可されたクラスだけが継承できるという点が最大の特徴です。これにより、開発者は意図しないサブクラスの乱立を防ぎ、安全で堅牢なクラス設計を行うことが可能になります。
sealedクラスを活用することで、ドメインモデルの状態管理やセキュアなAPI設計、ビジネスルールの厳密な制御がしやすくなります。特にドメイン駆動設計(DDD)との相性が良く、状態を表現する抽象的な型に対して、明確な具象クラスだけを許可することで、より安全で明確なコードになります。
Java sealedクラスの構文と設計パターンを振り返る
sealedクラスの基本構文では、sealedキーワードとpermits句をセットで使用します。また、許可されたサブクラスには必ずsealed・non-sealed・finalのいずれかの修飾子を付けなければなりません。
public sealed class Notification permits Email, Sms {
}
public final class Email extends Notification {
}
public non-sealed class Sms extends Notification {
}
このように、継承の範囲を意図的に制御できることで、プログラムの安定性が高まります。また、インターフェースにもsealedを使うことで、多態性と安全性を両立した設計が可能です。
実務でも活かせるsealedクラスのユースケース
sealedクラスは、開発現場でも多くのメリットを発揮します。たとえば、処理結果の表現(成功・失敗)、APIレスポンスの型、安全な状態遷移モデルなど、制御の必要な部分に最適です。
public sealed interface ApiResponse permits SuccessResponse, ErrorResponse {
}
public final class SuccessResponse implements ApiResponse {
private final String message = "成功しました";
}
public final class ErrorResponse implements ApiResponse {
private final String error = "エラーが発生しました";
}
sealedクラスを使えば、IDE上での補完や静的解析もより効果的になり、保守性と可読性が向上します。Javaの継承構造を明確に定義したい場合には、sealedクラスはとても信頼できる選択肢となるでしょう。
生徒
「sealedクラスって、Javaのクラス設計にかなり便利なんですね。制限をかけることで、意図しない継承を防げるのが安心です。」
先生
「そうだね。特にチーム開発では、クラスの使い方を統一するためにもsealedクラスは役立つよ。」
生徒
「sealedとfinal、non-sealedの使い分けも理解できました!特に状態管理に使えるのは、今後活かせそうです。」
先生
「その通り。設計の自由度を保ちつつ、しっかり制御するのがJavaのsealedクラスの強みなんだ。ぜひ実践でも活用してね。」