Sealed Classes and interfaces

In this post under Java, I will explain with example the purpose of Sealed classes and interfaces.

Sealed classes are the classes that doesn’t allow themselves to be inherited by any unspecified classes. Only those classes which are permitted by sealed classes, are allowed to inherit the sealed class.

Lets take an example.

A “Shape” class if not sealed can be extended by “Square” and “Rectangle” class and it is correct as “Square” and “Rectangle” is a child of “Shape” class.

But nothing is stopping any other non-related class to extend the “Shape” class.

For example, an “Apple” can also extend the “Shape” class. It is not right as there is no “is-a” relationship but nothing is preventing from happening it.

That is where “Sealed classes” come into picture.

We mark the “Shape” class as sealed by using the “sealed” keyword and list the classes that are permitted to extend “Shape” class using “permits” keyword as shown below in the snippet.

Shape class

package core.sealed.classes;

public sealed class Shape permits Square, Rectangle {
}

In the above code, we have used the “sealed” keyword next to “class” keyword informing the compiler that this is a “Sealed” class.

Then we have used the “permits” keyword to list the classes that are only allowed to extend this “Shape” class.

As a result of which, if “Apple” class tries to extend “Shape” class, we will get a compiler error.

Now since the “Square” and “Rectangle” class extend “Shape”, we have to mention whether they also are “Sealed class”, “Non Sealed class”, or “Final class”.

We know how to declare “Square” and “Rectangle” class as “Sealed” or “Final” class. Let’s skip that.

But we need to know what is “non sealed class”.

“Non sealed classes” are just like any normal class, the only difference being having the “non-sealed” keyword as shown below

Square and Rectangle class

package core.sealed.classes;

public non-sealed class Square extends Shape {
}
-----------------------------
package core.sealed.classes;

public non-sealed class Rectangle extends Shape {
}

As shown in the above code snippet, I have declared “Square” and “Rectangle” classes extend sealed class “Shape” but they themselves are not sealed by using the “non-sealed” keyword.

That means they can be extended by any unspecified class as shown below

Lemon class

package core.sealed.classes;

public class Lemon extends Square {
}

The above inheritance relationship is permitted even though it is not logical.

So a class that extends a sealed class must be declared either “sealed”, “non-sealed” or “final”.

We can apply the “sealed” keyword to an interface also.

When an interface is declared “sealed”, only those classes listed in “permits” section can implement it and only those interfaces listed in “permits” section can extend it.

Lets take an example, we will declare “Shape” as an interface, “Square” as a class and “Rectangle” as an interface.

So at the end the code snippet will be as shown below

package core.sealed.interfaces;

public sealed interface Shape permits Square, Rectangle {
}

The “Square” class and “Rectangle” interface will be as shown below

package core.sealed.interfaces;

public non-sealed class Square implements Shape {
}
---------------------------
package core.sealed.interfaces;

public non-sealed interface Rectangle extends Shape {
}

The interface that extends a sealed interface must be declared either “sealed” or “non-sealed”

Leave a comment