Wednesday, March 13, 2024

Java Sealed Classes and Interfaces

Sealed classes became a standard feature in Java 17. In Java 15 and 16 it was a preview feature. In this tutorial we'll see why do you need Sealed classes or interface in Java and how to use them


Why sealed classes and interfaces

Java is an object-oriented language and does support the object-oriented principal Inheritance. But if you notice Inheritance in Java doesn't provide much control over which classes should be permitted to extend a parent class. In fact, in Java, it is all or none kind of scenario, if you have a normal class then any class can extend it, or in case of a final class it can't be extended by any class.

That's what sealed class provides you; a fine grained control over inheritance. By sealing a class, you can specify which classes are permitted to extend it and prevent any other arbitrary class from doing so.

Same way with sealed interfaces you can specify which classes are permitted to implement it and which interfaces are permitted to extend it.

How to create a sealed class

For creating a sealed class in Java, you have to use the following steps-

  1. To create a sealed class, add the sealed modifier to its declaration.
  2. Add the permits clause to specify the classes that may extend the sealed class.
  3. The extending class must use one of the following modifiers to describe how it continues the sealing initiated by its superclass-
    • final: Cannot be extended further
    • sealed: Can only be extended by its permitted subclasses
    • non-sealed: Can be extended by any other class

Sealed class Java example

For example, the following declaration of Account specifies three permitted subclasses SavingAccount, CurrentAccount and SalaryAccount.

public sealed class Account permits SavingAccount, CurrentAccount, SalaryAccount{
	private double balance;
	public void withdraw(double amount) {
		balance = balance - amount;
	}
	public void deposit(double amount) {
		balance += amount;
	}
}

Define the following three permitted subclasses SavingAccount, CurrentAccount and SalaryAccount in the same module or in the same package as the sealed class Account.

SavingAccount.java

public sealed class SavingAccount extends Account permits PrivilegedSavingAccount{
	private double rateOfInterest = 4;
}

CurrentAccount.java

public final class CurrentAccount extends Account{
	private double rateOfInterest = 0.5;
}

SalaryAccount.java

public non-sealed class SalaryAccount extends Account{
	private double rateOfInterest = 3;
}

SavingAccount has a further subclass, PrivilegedSavingAccount which should also follow the same procedure of permitting 3 types of sub-classes for a sealed class.

PrivilegedSavingAccount.java

public final class PrivilegedSavingAccount extends SavingAccount{
	private int priority = 1;
}

If any class which is not in the list of permitted classes try to extend the Account class gives the following error.

public sealed class Test extends Account{

}

Sealed class or interface lacks the permits clause and no class or interface from the same compilation unit declares Test as its direct superclass or superinterface

Constraint on sealed and permitted sub-classes

  1. All the permitted subclasses must be accessible by the sealed class at compile time. For example, to compile Account.java, the compiler must be able to access all of the permitted classes of Account: SavingAccount.java, CurrentAccount.java and SalaryAccount.java. Out of these classes SavingAccount is a sealed class so compiler also needs access to PrivilegedSavingAccount.java.
  2. Permitted subclasses must directly extend the sealed class.
  3. Permitted subclasses must be in the same module as the sealed class or in the same package.
  4. You can define permitted subclasses in the same file as the sealed class. If you do so, then you can omit the permits clause.
    public sealed class Account {
    	private double balance;
    	public void withdraw(double amount) {
    		balance = balance - amount;
    	}
    	public void deposit(double amount) {
    		balance += amount;
    	}
    }
    
    final class CurrentAccount extends Account{
    	private double rateOfInterest = 0.5;
    }
    
    non-sealed class SalaryAccount extends Account{
    	private double rateOfInterest = 3;
    }
    
    sealed class SavingAccount extends Account permits PrivilegedSavingAccount{
    	private double rateOfInterest = 4;
    }
    
    final class PrivilegedSavingAccount extends SavingAccount{
      private int priority = 1;
    }
    
    

Defining Sealed interface

A sealed interface lets you specify the interfaces that can extend it and the classes that can implement it. It follows rules similar to sealed classes.

You can't declare an interface using the modifier final so you can specify an inheriting interface as either sealed or non-sealed but not final.

sealed public interface MyInterface permits MyClass, AnotherInterface{

}
public final class MyClass implements MyInterface{

}
public non-sealed interface AnotherInterface extends MyInterface{

}

That's all for this topic Java Sealed Classes and Interfaces. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Java Record Class With Examples
  2. Lambda Expressions in Java 8
  3. Var type in Java - Local Variable Type Inference
  4. Effectively Final in Java 8
  5. Switch Expressions in Java 12

You may also like-

  1. Java Stream - findFirst() With Examples
  2. Java Map containsValue() - Check if Value Exists in Map
  3. String Vs StringBuffer Vs StringBuilder in Java
  4. How to Create PDF From XML Using Apache FOP
  5. Swap or Exchange Two Numbers Without Using Any Temporary Variable Java Program
  6. Setting Wild Card Route in Angular
  7. Run Python Application in Docker Container
  8. Python while Loop With Examples

No comments:

Post a Comment