6

For the first time in a LTS version of Java (Java 17) we have the sealed keyword that, in a nutshell, give us the possibility to restrict the hierarchy:

public abstract sealed class Person
    permits Employee, Manager {
 
    //...
}

If I want to create a new subclass that extend the Person base class, I have to modify the base class too. Is it this against the open close principle?

Brian Goetz
  • 90,105
  • 23
  • 150
  • 161
SGiux
  • 619
  • 3
  • 10
  • 34
  • 1
    Note that we've always had `final` which gives us the possibility to restrict the hierarchy. Sealing extends this beyond individual concrete classes. – Brian Goetz Dec 09 '21 at 16:16
  • Good question, but I can't help myself from commenting on your example. You could be heading for trouble if you define "employee" and "manager" to be kinds of "person." In reality, "employee" and "manager" are _roles_ that people play, and sometimes people switch roles. Java instances, on the other hand, can never change their class. – Solomon Slow Apr 09 '22 at 14:30
  • That's precisely why I find sealed classes ... problematic at best. To me, they look like a crutch for base classes with a contract so complex that the author doesn't trust client programmers to implement it correctly and is also unable to guard against subclasses implementing it incorrectly. – user625488 Dec 13 '22 at 11:14

1 Answers1

19

The open-closed principle is not a law of physics, but merely a guideline that may be useful in some cases. Another useful principle, from Effective Java, is "Design for extension, or else prohibit it." (Also: "Prefer composition to inheritance".) Personally I find the guidance from Effective Java far more useful than the open-closed principle; designing classes for extension is rife with tradeoffs, often questionable ones.

Sealed classes can be thought of as a generalization of final classes, just applied at a different level of granularity. Previously, prohibiting extension was only available to concrete classes (final), but now it is available to entire hiearchies.

But, the premise of the question -- "If I want to add..." -- is in itself questionable. Sealed classes are a mechanism that allows API owners to maintain the integrity of their APIs, by controlling all of the implementations of an abstraction (or by limiting extension to specific extension points.) The API owner has already designed and implemented the hierarchy with the assumption that there is a fixed set of implementations; "adding" to it then really becomes "throwing out their design and replacing it with something different." If an API hasn't been designed for extension, second-guessing the designer's intent is risky business.

Brian Goetz
  • 90,105
  • 23
  • 150
  • 161
  • 1
    So, the used of sealed classes can be a way to show that a piece of the application is not thought to be extendible. When I was writing the question I was thinking about the sealed classes in Kotlin. In this case the JetBrain developers have designed them in different way (maybe they have took in consideration this principle). In Kotlin you don't have to specify the list of the permitted subclasses in the base class. – SGiux Dec 08 '21 at 20:19
  • 3
    In the most common cases (when the subtypes are co-declared with the sealed type), the Java compiler can infer the list of permitted subtypes as well. – Brian Goetz Dec 08 '21 at 21:25
  • If the API hasn't been designed for extension, but abstract base classes, rather than interfaces or final classes, are exposed through the API, it's bad design, IMO. – user625488 Dec 13 '22 at 11:43