What is the difference between a final and a non-sealed class in Java 15's sealed-classes feature?

2.8k views Asked by At

I have the following sealed interface (Java 15):

public sealed interface Animal permits Cat, Duck {

    String makeSound();
}

This interface is implemented by 2 classes:

public final class Cat implements Animal {

    @Override
    public String makeSound() {
        return "miau";
    }
}

public non-sealed class Duck implements Animal {

    @Override
    public String makeSound() {
        return "quack";
    }
}

Can someone tell me the difference between final and non-sealed? final stops me from creating other sub-classes but what behavior does non-sealed apply to Duck?

3

There are 3 answers

1
akuzminykh On BEST ANSWER
  • As you've marked Cat as final, no other class can extend Cat.
  • As you've marked Duck as non-sealed, any class can extend Duck.

When marking a class as sealed, all directly extending classes (the ones after the permits clause) have to be marked either as final, sealed or non-sealed:

  • Marking a class that extends a sealed class as sealed, applies the same effect on it: Only classes specified after the permits clause are allowed to extend it.

  • non-sealed just "breaks the seal", so the effect doesn't have to be carried on down the hierarchy. The extending class is open (again) for being extended by unknown subclasses itself.

  • final is effectively the same as sealed without any class specified after the permits clause. Notice that specifying nothing after permits is not possible, so sealed cannot replace final.

0
Moniruzzaman rony On

Final and non-sealed classes have some differences.

final class: you can't inherit this class, it's impossible to extend this class to other class on the other hand.

non-sealed class: it's possible to inherit this class from others.

For example:
This sealed interface which interface only permitted for Cat & Duck class. Note that Cat & Duck must be final, non-sealed, or sealed class:

public sealed interface Animal permits Cat, Duck {
    String makeSound();
}

Now, I am creating Cat & Duck class. Here Cat is the final class and another one is non-sealed class.

public final class Cat implements Animal {

    @Override
    public String makeSound() {
        return "miau";
    }
}

public non-sealed class Duck implements Animal {

    @Override
    public String makeSound() {
        return "quack";
    }
}

So if you can try to inherit the Cat class, you can't, got compilation error because Cat class is final. On another hand, the Duck class is extendable because it's non-sealed class Like,

//Got Error
public class MyCat extends Cat {
    .......
}

//Error not show.Duck class is extendable
public class MyDuck extends Duck {
    .....
}
0
Praj On

A final class has zero subclasses, meaning no other class can extend it. Any class can extend the non-sealed class.

When you mark a class as sealed, only the permitted subclasses can extend it and can have only these modifiers final, sealed, or non-sealed:

public sealed class NumberSystem
    // The permits clause has been omitted
    // as all the subclasses exists in the same file.
{ }
non-sealed class Decimal extends NumberSystem { .. }
final class NonRecurringDecimal extends Decimal {..}
final class RecurringDecimal extends Decimal {..}

Though, the NumberSystem root level hierarchy is closed to set of known classes, you can allow the sub hierarchies to be open by using the non-sealed keyword.

The sealed and non-sealed combination allows you to restrict parts of your hierarchy but not all.

In the below diagram, we restricted the root hierarchy of the sealed class NumberSystem to a known set of subclasses. However, the non-sealed Decimal class allows any unknown subclass such as RecurringDecimal to extend it.