Permitted Direct Subtypes in Java Sealed Classes
The `permits` clause declares which classes or interfaces may directly extend or implement a sealed type. It restricts the inheritance hierarchy to explicitly authorized direct subtypes.
A sealed class or interface controls which types can be its direct subtypes. The allowed types are declared with the `permits` clause, making the intended inheritance hierarchy explicit.
For example, `sealed class Shape permits Circle, Rectangle` allows `Circle` and `Rectangle` to directly extend `Shape`. A different class cannot directly extend `Shape` unless it is listed as a permitted subtype.
The permitted subtype must also declare how inheritance continues. A direct subclass of a sealed class must be declared `final`, `sealed`, or `non-sealed`. This ensures the compiler knows whether that branch ends, remains restricted, or becomes open to further inheritance.
The compiler can use the closed set of permitted direct subtypes for checks such as exhaustiveness in pattern matching. This is one reason sealed hierarchies are useful when modeling a fixed set of domain variants.
Key points
- The `permits` clause lists the allowed direct subtypes.
- Only listed types can directly extend or implement the sealed type.
- Each direct subtype must be `final`, `sealed`, or `non-sealed`.
- Sealed hierarchies enable compiler reasoning about a known set of direct subtypes.
Interview questions
What does the `permits` clause do in a Java sealed type?
It specifies the classes or interfaces that are allowed to be direct subtypes of the sealed type. Any other type is prevented from directly extending or implementing it. The permitted subtype must also use `final`, `sealed`, or `non-sealed` to define what happens next in the hierarchy.
Why must a direct subtype of a sealed class be `final`, `sealed`, or `non-sealed`?
The language requires each direct subtype to explicitly determine whether inheritance stops or continues. `final` closes that branch, `sealed` continues restricting it, and `non-sealed` opens that branch to unrestricted inheritance. This keeps the inheritance structure explicit.
Can a class extend a sealed class without appearing in its `permits` clause?
No, it cannot be a direct subtype unless it is permitted by the sealed type. The compiler checks the declared inheritance relationship against the permitted set. This is what makes the direct inheritance boundary closed.
How do sealed types and `permits` help with pattern matching?
A sealed type provides a compiler-known set of permitted direct subtypes. Pattern matching can use that closed hierarchy when determining whether all relevant cases have been handled. This can allow an exhaustive switch without relying on a general default case, depending on the particular Java language features and types involved.