On 8/20/2019 12:40 PM, Brian Goetz wrote:
Gathering the various threads in this discussion, here’s what seems a sensible 
landing place:

1.  A sealed _class_ with no permitted subtypes is a final class.  The 
distinction between declared-sealed-with-no-permits and declared-final is 
erased away.  [*]

2.  Sealed abstract classes and interfaces with no permitted subtypes are 
illegal.

3.  If a sealed type does not specify a permits list, it can be inferred by 
enumerating the subtypes in the same compilation unit.

4.  If a concrete class is a subtype of a sealed type declared in the same 
compilation unit, and none of the modifiers { sealed, non-sealed, final } are 
present, it is inferred to be sealed with an inferred permits list (which, 
according to (1), may be treated as final if there are none.) >
5.  (optional) It is an error to specify an explicit permits list if `sealed` 
is not specified.

6.  Otherwise, a subtype of a sealed type must have exactly one of the 
following modifiers: sealed, non-sealed, final.

I see two committed principles here:

1. Permitted subtypes are common; their enumeration isn't. It's almost like explicit `permits` is a separable feature that could be set aside for now.

2. Ceremony reduction is important enough to treat concrete direct subclasses of a sealed type specially.

However, that special treatment comes at the expense of another principle: "leaf nodes [implicitly final classes] are obvious". I was hoping to have this because implicitly final classes [sealed with zero permitted subtypes] are The Show. Below, it's kinda hard to figure out that class C is NOT a leaf node:

--I.java--
sealed interface I {}    // implicitly `permits C`

class C implements I {}  // implicitly `sealed` and `permits D`

... lots of other stuff ...
class D extends C {}     // implicitly `sealed` w/ no permitted subtypes
----------

whereas below, the leaf nodes are mostly obvious by virtue of how the intermediate hierarchy is explicitly `sealed`:

--I.java--
sealed interface I {}            // implicitly `permits J`
sealed interface J extends I {}  // plainly not a leaf
sealed abstract class AC implements J {}  // plainly not a leaf

class PolarData extends AC {}      // maybe a leaf
class CartesianData extends AC {}  // maybe a leaf
// EOF, so yes, PolarData and CartesianData are indeed leaves
----------

tl;dr We're back to having both sealed-ness and the potentially-non-trivial permits list be implicit, which was earlier thought to strain the reader. If we said that concrete direct subclasses of a sealed type were implicitly final, then ceremony reduction would still be high, and if you really don't want them to be leaf nodes then say `sealed` or `non-sealed`.

Alex

Reply via email to