Refinements for sealed types
Alex Buckley
alex.buckley at oracle.com
Tue Aug 20 21:56:26 UTC 2019
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
More information about the amber-spec-experts
mailing list