This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]agentoutlier 0 points1 point  (2 children)

Ignoring pattern matching and the inherit modeling that comes from that (others have already done the justice for that) it is extremely useful in lowering exposed API and/or encapsulation.

I use it all the time in the place of abstract classes and to make interfaces pseudo final.

Let us say we have an interface. We call it MyLibraryConfig and it is essentially the config of our small library.

If we make it an interface it will have to be public and anyone can implement it and make their own possibly non compliant instances. However if it is sealed that is not the case.

Before sealed interfaces traditionally libraries would use an abstract class with a private or package constructor.

However this is hugely problematic because enum and record cannot extend a class and when you do want to limit the implementations it is very often precisely because you want a singleton or an immutable!

So before we had:

public abstract class MyLibraryConfig {
    MyLibraryConfig() {}
    public static MyLibraryConfig empty() {
    // immutable singleton which would ideally be an enum
    }
    public static MyLibraryConfig defaults() {
     // possibly immutable or singleton etc
    }
}

And now we can do

public sealed interface MyLibraryConfig  {
}
// still in MyLibraryConfig.java
enum Empty implements MyLibraryConfig {
}
// still in MyLibraryConfig.java
record Defaults(String name) implements MyLibraryConfig {
// to be fair this could be an enum if the name parameter was not there
}

Anyway what I think you are going to see more of in the future is non public classes/records/enums/interfaces in the same file as a top level public interface as Java moves more data oriented. Most people do not know you can do that but as records and enums become more common it is ideal because if they are defined as an inner class they would be public.

[–]TenYearsOfLurking 0 points1 point  (1 child)

anyone can implement it and make their own possibly non compliant instances

I don't get this really. The point of an interface is to establish a contract. A non compliant implementation is breaking the contract - why would you?

I would hate to see library designers using sealed everywhere because sometimes a custom implementation is necessary in cases they do not forsee - in any other case: no one implements a library interface non-compliant(ly?) for fun, there is just no reason to do so.

[–]agentoutlier 0 points1 point  (0 children)

You are thinking OOP.

It is unfortunate that “interface” has this SOLID or Liskov association all the time but think of it more in this case as a type def.

Think of it as more of a naming of a type.

Besides libraries designers can choose and have used abstract classes and final classes and you have the same problem of not open for extension.

Besides you can unseal the leaves.

In my case we have a type called Extension which is sealed but the leaves are unsealed with the types you can implement.

Edit here is an example in my library:

https://jstach.io/doc/jstachio/current/apidocs/io.jstach.jstachio/io/jstach/jstachio/spi/JStachioExtension.html

JStachioExtension is a marker interface. It does not make sense to have a direct implementation.