RFR: JEP 360: Sealed Types (Preview)
Brian Goetz
brian.goetz at oracle.com
Wed Apr 15 12:58:01 UTC 2020
This is a good observation, but I think you've overstated somewhat (and,
to some degree, this incompatibility may actually be doing your clients
a favor.)
Here's the case I think you're concerned about:
// Maintenance domain A
sealed interface X permits X.A, X.B {
public class A implements X {}
public class B implements X {}
}
// Maintenance domain B
int z = switch (x) {
case A a: ...
case B b: ...
// no default
}
Your concern is that the compiler will accept this switch as exhaustive
(so far, that's good), and later, if we refactor the X subtypes, this
might be a source-incompatible change. (It always has been an
incompatible change to remove a class, or to remove a supertype from a
class, so that's not what we're talking about here -- we're talking
about removing it from the permits clause.)
Indeed, using the sealing information to switch exhaustively over a
sealed type is a form of *tight coupling*; client code that wants to
take advantage of this information should either be part of the same
maintenance domain as the hierarchy, or be confident that the API is set
in stone, or be ready to change when the hierarchy changes. These are
all reasonable choices to make with one's eyes open, but I think your
concern is that this sort of tight coupling could arise _accidentally_
from ordinary use.
And, that's true. However, I think it's not as bad as you think (and
this has already been discussed a fair bit on the EG list.) First,
merely dropping A from the permits clause is a binary-compatible change,
so existing binaries will continue to run just fine. It is
source-incompatible, but I would argue that this is, in many cases,
better than the alternative. Getting a compilation error here is type
checking at work; the compiler has identified an assumption baked into
your program that is no longer valid. If it's a matter of having
dropped a permitted subtype, the change to your code is easy -- just
drop the case, and you are correct again. If its a matter of having
added a permitted subtype, the change is also easy; if you don't want to
handle the new case, add a default clause that throws (which is what you
would have done in the first place if you didn't have the option to lean
on exhaustiveness checking in the compiler.)
It is certainly good to write down some promoted practices for using
sealed types, and this is something to consider pointing out, but the
JEP is not the place for that; if it were, JEPs would be 100 pages (and
then people would complain they were too big, as in fact some people
already do.) For other features (e.g., var, text blocks) there have
been separate "style guide" documents that have the luxury describe the
nuances in more detail.
On 4/15/2020 8:32 AM, Kłeczek, Michał wrote:
> Hi Vicente,
>
> IMHO there is one thing I think is worth pointing out in the
> documentation (as it is going to be cited on thousands of web sites):
>
> One has to be very careful when exposing sealed types with only public
> permitted subtypes in public APIs.
> Doing that makes it impossible to change the list of subtypes - both
> removal and adding of a subtype is an incompatible change.
>
> I think it might be surprising for many library developers and I've
> raised the concerns about this before - maybe it is a good idea to
> make it more apparent.
>
> Thanks,
> Michal
>
> On 13/04/2020 18:03:18, "Vicente Romero" <vicente.romero at oracle.com>
> wrote:
>
>> Hi all,
>>
>> The sealed types JEP was already reviewed a while back when we were
>> planning to include it in JDK14. It finally fell off that boat but it
>> is being considered now for JDK15. There have been some changes since
>> then mostly related to subtypes of a sealed type. Before we were
>> planning to infer finality, sealness or non-sealness in the subtypes.
>> We steered away from that direction in favor of explicit declaration
>> at the subtype. I would like to ask for another review of the current
>> version of the JEP that reflects these changes. The JEP is at [1] and
>> the last version of the spec is at [2],
>>
>> Thanks,
>> Vicente
>>
>> [1] https://bugs.openjdk.java.net/browse/JDK-8227043
>> [2]
>> http://cr.openjdk.java.net/~gbierman/jep360/jep360-20200228/specs/sealed-types-jls.html
>>
>
More information about the amber-dev
mailing list