13

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?

Naman
  • 27,789
  • 26
  • 218
  • 353
Michael Kemmerzell
  • 4,802
  • 4
  • 27
  • 43
  • 2
    [A permitted subclass may be declared non-sealed so that its part of the hierarchy reverts to being open for extension by unknown subclasses. (A sealed class cannot prevent its permitted subclasses from doing this.)](https://openjdk.java.net/jeps/360) – Youcef LAIDANI Sep 19 '20 at 18:39
  • 3
    A `final` class can never be subclassed (old, old functionality). A `non-sealed` class is specifically opening up a class to be subclassed, which is needed when its base class is `sealed`. – Andreas Sep 19 '20 at 19:20
  • 2
    Sealing is a generalization of finality; a final class can be extended by nothing, a sealed class by the explicit list of permitted subtypes. (A final class is like a selaed one with an empty permits list.) Other languages have gone the route that a permitted subtype of a sealed type can be arbitrarily extended, but this often surprises people and can lead to bugs. So Java requires you to be explicit about it: for a subtype of a sealed type, you have to pick one: final, sealed, or open for extension. (Records are implicitly final so you don't have to say it explicitly.) – Brian Goetz Sep 26 '20 at 14:13

3 Answers3

18
  • 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.

akuzminykh
  • 4,522
  • 4
  • 15
  • 36
2

Final and non-sealed class has some differences.

final class: you can't inherit this class. I mean that you can't extend this class to other class on the other hand.

non-sealed class: you can 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 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

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.

Praj
  • 451
  • 2
  • 5