Basics of Sealed class in Java ?
A sealed class in java, is a new feature introduced to control class inheritance and hierarchy. When a class is declared as sealed using the sealed
keyword, it specifies which classes are allowed to extend it. This restriction promotes a controlled and predictable class hierarchy by permitting only specific subclasses to extend the sealed class.
The permitted subclasses are explicitly listed using the permits
keyword within the sealed class declaration. These permitted subclasses must directly extend the sealed class and cannot be extended further by any other classes outside the specified list.
Example of Sealed class in java
Let’s take an example with a Car
hierarchy to illustrate the concept. Suppose Car
class is declared as sealed, indicating that only certain subclasses are allowed to inherit from it. These permitted subclasses—Sedan
, SUV
, and SportsCar
—are explicitly specified within the Car
class using the permits
keyword.
sealed class Car permits Sedan, SUV, SportsCar
Each permitted subclass (Sedan
, SUV
, SportsCar
) extends the Car
class and provides its own implementation of method say drive()
method. This method showcases specific behavior unique to each type of car, allowing for individualized driving behaviors for sedans, SUVs, and sports cars.
Relationship of final, abstract & sealed keywords:
Keyword final:
The final
keyword in Java is used to restrict the modification of classes, methods, and variables.
- When applied to a class, it indicates that the class cannot be extended or subclassed.
- In the case of methods, marking a method as
final
means it cannot be overridden in any subclass. - In case of Variables marked as
final
, value of variable cannot be changed once initialized, hence making the variable as constants.
Abstract keyword:
An abstract
class in Java cannot be instantiated on its own and typically serves as a blueprint for other classes. It may contain abstract methods (methods without a body) that must be implemented by its subclasses. Abstract classes provide a way to define common behaviors and attributes to be shared among multiple subclasses.
Sealed Keyword:
The sealed
keyword, introduced in recent Java versions, restricts class inheritance by specifying which subclasses are allowed to extend a particular class. When a class is declared as sealed
, it permits a specific list of subclasses using the permits
clause. Only the specified permitted subclasses can directly extend the sealed class, ensuring a controlled hierarchy and preventing further subclassing beyond the specified ones.
Summary of final, abstract & sealed keyword:
Final
restricts modification, preventing extension (for classes), overriding (for methods), or reassignment of values (for variables).Abstract
classes cannot be instantiated and serve as blueprints, often containing abstract methods to be implemented by subclasses.Sealed
classes control inheritance by allowing only specified subclasses to extend them, promoting a predictable and limited class hierarchy.
Dive deep into sealed classes in java:
What is the need of sealed class?
Sealed classes were introduced in Java to provide more control over class hierarchies and to enhance code predictability and maintainability. This new feature offers a more structured approach to inheritance by restricting which classes can extend a sealed class and hence its kind of restriction applied at top level only. We can think of sealed classes like firewall (analogy).
Firewall, its primary role is to control and restrict incoming and outgoing network traffic based on predefined rules and permissions. Similarly, sealed classes in Java act as a form of restriction mechanism, governing class inheritance by allowing only specified subclasses to extend a particular sealed class.
Just as a firewall specifies which types of traffic are allowed or blocked, sealed classes specify a predefined list of permitted subclasses using the permits
clause. This restriction serves as a barrier, similar to a firewall, preventing unauthorized or unintended extensions of a sealed class beyond the specified subclasses.
However, it’s essential to note that while the analogy between sealed classes and firewalls can provide a conceptual understanding, they operate in different domains—sealed classes specifically within Java’s object-oriented programming, and firewalls in the realm of network security. Despite this, drawing parallels can aid in understanding how sealed classes function as a controlled access mechanism within the Java class hierarchy.
So, what are the Motivations for sealed classes?
The primary motivation behind introducing sealed classes is to promote a controlled and predictable class hierarchy within applications. By specifying a list of permitted subclasses using the permits
clause, a sealed class dictates exactly which classes are allowed to extend it. This restriction prevents the multiplication of numerous, unintended subclasses and helps maintain a well-defined and limited set of subclasses. Hence, we can prevent the unnecessary pollution of classes, which ideally is not needed.
Additionally, sealed classes aim to enhance code readability and maintainability by providing a clearer understanding of the class hierarchy. They make it easier for us to understand and manage the relationships between classes within a hierarchy, ensuring that only specific subclasses, as intended by the design, can extend a particular sealed class. Suppose, architect of application design the classes without sealed keyword. It would give full liberty to development team to extend or create any number of subclass (even without their need), it would indeed defeat the purpose of good design created by architect.
Additionally, sealed classes contribute to code robustness and security by limiting the scope of inheritance, preventing potential issues that might arise from unintended extensions or misuse of class inheritance.
As we have discussed the basic concepts of sealed class, let’s take an example of car classes and create basic class hierarchy to explore further.
Example: How to Implement Sealed class in java?
We will create a Base class Car, which we will declared as sealed class. We will create 3 subclasses of this Car class say: Tesla
, BMW
, and Mercedes
.
Car class definition (sealed):
The Car
class is declared as a sealed class using the sealed
keyword, followed by the permits
clause specifying the permitted subclasses. This restriction ensures that only the specified subclasses can extend the Car
class, controlling the class hierarchy.
sealed class Car permits Tesla, BMW, Mercedes
Car Subclass Implementations:
Each permitted subclass (Tesla
, BMW
, Mercedes
) extends the Car
class and provides its own implementation of the drive()
method.
Test Sealed class implement in Main Class:
The Main
class demonstrates how objects of each subclass (myTesla
, myBMW
, myMercedes
) can be instantiated and used through polymorphism.
The driveCar()
method takes a Car
object as an argument and calls its startEngine()
, drive()
, and stopEngine()
methods, showcasing polymorphic behavior.
Program: Inheritance using Sealed classes in Java (example)
package org.example; public sealed class Car permits Tesla, BMW, Mercedes { public void startEngine() { System.out.println("Engine started."); } public void stopEngine() { System.out.println("Engine stopped."); } public void drive() { System.out.println("Driving..."); } }
Tesla class implementing Car (Sealed) class:
package org.example; final class Tesla extends Car { public void drive() { System.out.println("Tesla: Autopilot engaged."); } }
BMW class implementing Car (Sealed) class
package org.example; final class BMW extends Car { public void drive() { System.out.println("BMW: Ultimate driving experience."); } }
Mercedes class implementing Car (Sealed) class
package org.example; final class Mercedes extends Car { public void drive() { System.out.println("Mercedes: Smooth and luxurious drive."); } }
Main class invoking sealed subclasses (java)
package org.example; public class Main { public static void main(String[] args) { Car myTesla = new Tesla(); Car myBMW = new BMW(); Car myMercedes = new Mercedes(); driveCar(myTesla); driveCar(myBMW); driveCar(myMercedes); } public static void driveCar(Car car) { car.startEngine(); car.drive(); car.stopEngine(); System.out.println(); } }
Output: Sealed class implementation in Java (example)
Engine started. Tesla: Autopilot engaged. Engine stopped. Engine started. BMW: Ultimate driving experience. Engine stopped. Engine started. Mercedes: Smooth and luxurious drive. Engine stopped.