Java Sealed Classes
Java 17で正式導入された継承を制限するクラスを学びます。
Sealed Classes とは
継承できるクラス/インターフェースを明示的に指定する機能。
// 従来: 誰でも継承可能
public abstract class Shape { }
// どこからでも extends Shape できてしまう
// Sealed: 継承を制限
public sealed class Shape permits Circle, Rectangle, Triangle { }
// Circle, Rectangle, Triangle のみが継承可能
基本構文
// sealed で宣言、permits で許可するサブクラスを列挙
public sealed class Shape permits Circle, Rectangle {
// 共通の実装
}
// サブクラスは final, sealed, non-sealed のいずれかが必須
public final class Circle extends Shape {
private final double radius;
public Circle(double radius) { this.radius = radius; }
}
public final class Rectangle extends Shape {
private final double width, height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
}
サブクラスの修飾子
final
これ以上の継承を禁止。
public sealed class Animal permits Dog, Cat {}
public final class Dog extends Animal {}
// Dog を継承することはできない
sealed
さらに継承を制限付きで許可。
public sealed class Animal permits Mammal, Bird {}
public sealed class Mammal extends Animal permits Dog, Cat {}
public final class Dog extends Mammal {}
public final class Cat extends Mammal {}
public final class Bird extends Animal {}
non-sealed
継承の制限を解除(オープンにする)。
public sealed class Vehicle permits Car, Motorcycle, CustomVehicle {}
public final class Car extends Vehicle {}
public final class Motorcycle extends Vehicle {}
// non-sealed: 誰でも継承可能
public non-sealed class CustomVehicle extends Vehicle {}
// CustomVehicle は誰でも継承できる
public class ElectricScooter extends CustomVehicle {}
Sealed Interface
public sealed interface Result<T> permits Success, Failure {
T getOrThrow();
}
public record Success<T>(T value) implements Result<T> {
@Override
public T getOrThrow() {
return value;
}
}
public record Failure<T>(String error) implements Result<T> {
@Override
public T getOrThrow() {
throw new RuntimeException(error);
}
}
permits の省略
サブクラスが同じファイル内にある場合、permits を省略できる。
// 同一ファイル内
public sealed interface Shape {
// permits は暗黙的
}
final class Circle implements Shape {
private final double radius;
Circle(double radius) { this.radius = radius; }
}
final class Rectangle implements Shape {
private final double width, height;
Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
}
Pattern Matching との組み合わせ
Sealed Classes の真価は Pattern Matching との組み合わせで発揮される。