Sealed
classes and interfaces specify who can extend or implement this class or
interface. A sealed class or interface can be extended or implemented only by
those classes and interfaces permitted to do so.
A class is
sealed by applying the sealed modifier to its declaration. For example, the
following declaration of Address specifies two permitted subclasses (TemporaryAddress,PermanentAddress).
Address.java
package com.sample.app.dto;
public sealed abstract class Address permits TemporaryAddress,PermanentAddress {
public abstract String getAddress();
}
TemporaryAddress.java
package com.sample.app.dto;
public final class TemporaryAddress extends Address{
@Override
public String getAddress() {
return "";
}
}
PermanentAddress.java
package com.sample.app.dto;
public final class PermanentAddress extends Address{
@Override
public String getAddress() {
return "";
}
}
The
classes specified by permits must be located near the superclass:
a.
either
in the same module (if the superclass is in a named module) or
b.
in
the same package (if the superclass is in the unnamed module).
There is
another alternative way to define a sealed class. When the permitted subclasses
are small in size and number, it may be convenient to declare them in the same
source file as the sealed class. When they are declared in this way, the sealed
class may omit the permits clause, and the Java compiler will infer the
permitted subclasses from the declarations in the source file
Animal.java
package com.sample.app.dto;
public abstract sealed class Animal {
public abstract String aboutMe();
public static Animal tiger() {
return new Tiger();
}
public static Animal lion() {
return new Lion();
}
}
final class Tiger extends Animal {
@Override
public String aboutMe() {
return "I am Tiger";
}
}
final class Lion extends Animal {
@Override
public String aboutMe() {
return "I am Lion";
}
}
In this
example, sealed class Animal is inferred to have two permitted subclasses
(Lion, Tiger).
SealedClassDemo1.java
package com.sample.app;
import com.sample.app.dto.Animal;
public class SealedClassDemo1 {
public static void main(String[] args) {
Animal lion = Animal.lion();
Animal tiger = Animal.tiger();
System.out.println(lion.aboutMe());
System.out.println(tiger.aboutMe());
}
}
Output
I am Lion
I am Tiger
What
happen if a non-permitted class try to extend a sealed class?
Compiler
throws an error by saying ‘class is not allowed to extend sealed class: Address’.
What
are the constraints on permitted classes?
a.
The
sealed class and its permitted subclasses must belong to the same module, and,
if declared in an unnamed module, the same package.
b.
Every
permitted subclass must directly extend the sealed class.
c.
Every
permitted subclass must choose a modifier to describe how it continues the
sealing initiated by its superclass.
1.
A
permitted subclass may be declared final to prevent its part of the class
hierarchy from being extended further.
2.
A
permitted subclass may be declared sealed to allow its part of the hierarchy to
be extended further than envisaged by its sealed superclass, but in a
restricted fashion.
3.
A
permitted subclass may be declared non-sealed so that its part of the hierarchy
reverts to being open for extension by unknown subclasses. (A sealed class
cannot prevent its permitted subclasses from doing this.)
You can
correlate the above points with below example.
Shape.java
package com.sample.app.dto;
public sealed class Shape {
}
final class Circle extends Shape {
}
sealed class Square extends Shape permits FilledSquare {
}
final class FilledSquare extends Square {
}
non-sealed class Rectangle extends Shape {
}
class MyRect extends Rectangle {
}
References
https://openjdk.org/jeps/360
Previous
Next
Home