Saiprashanth
Saiprashanth

Reputation: 481

How to restrict inheritance to a single subclass in Java

Suppose there is class A which is parent class and class B that extends A.

Now I should not allow to extend class A to class C (class C extends A), or any other class.

How to do that?

Upvotes: 14

Views: 2308

Answers (3)

Jimmy
Jimmy

Reputation: 1051

From Java 15 onward such use-case can be implemented by using sealed modifier and permits clause

The restriction of a class or interface to become a parent for a specific class or interface. Following are two use case one for class and another for interface.

1. Using Class: Suppose we have an class ClazzA, we want to restrict this class to extend only by class ClazzB. That is no any other class can extends ClazzA except ClazzB.

public abstract sealed class ClazzA permits ClazzB {

    final String str;
    
    public ClazzA(String str) {
        this.str = str;
    }

    public void method() {
        // TODO
    }

}

2. Using Interface: Suppose we have an interface InterfaceA, we want to restrict this interface to extend only by interface InterfaceB. That is no any other interface can extends except InterfaceB

public sealed interface InterfaceA permits InterfaceB {

    int method1();

    default int defaultMethod() {
        return 0;
    }

}

Upvotes: -1

scardon
scardon

Reputation: 744

That's why Java 17 has sealed classes. This feature was added as a preview feature in Java 15.

Sealed classes and interfaces restrict which other classes or interfaces may extend or implement them.

In your case you can do the following:-

public sealed class A permits B {

}

public class B extends A{ //No error

}

public class C extends A{  //error because class C is not permitted 

}

The Goals of Sealed classes in java are :-

  • Allow the author of a class or interface to control which code is responsible for implementing it.

  • Provide a more declarative way than access modifiers to restrict the use of a superclass.

  • Support future directions in pattern matching by providing a foundation for the exhaustive analysis of patterns.


IF you want a class not extendable, then you can use final.

public final class A{ //Cannot be extended by other classes.
}

Helpful links:

https://docs.oracle.com/en/java/javase/15/language/sealed-classes-and-interfaces.html

http://openjdk.java.net/jeps/409

https://www.baeldung.com/java-sealed-classes-interfaces

What are sealed classes in Java 17

Upvotes: 26

kaya3
kaya3

Reputation: 51034

If you are using an older version of Java, the natural solution is simply to make class A package-private. This prevents classes outside of the package from subclassing A directly.

If A itself does need to be exposed publicly, there is still a solution: declare another class PublicA which is public and final, where PublicA is a subclass of A with no additional or overridden members. Then classes in other packages can use PublicA instead of A, but they cannot subclass it.

The only other practical difference between PublicA and A is that the class B is a subclass of A but not a subclass of PublicA; so for example obj instanceof PublicA won't work to detect instances of B or other public subclasses of A. If an instanceof check like this might be required in other packages, then either a public interface can be exposed which A implements, or PublicA can expose a static method which returns arg instanceof A from inside the package, where it is allowed.

Upvotes: 5

Related Questions