RFR: JEP 360: Sealed Types (Preview)
Kłeczek, Michał
michal at kleczek.org
Wed Apr 15 14:06:40 UTC 2020
Actually I was talking about _adding_ a new permitted subtype (and this
is why I think it might be surprising and worth mentioning):
// Maintenance domain A
sealed interface X permits X.A, X.B
// added in version 1.1
, X.C
{
public class A implements X {}
public class B implements X {}
// added in version 1.1
public class C implements X {}
}
public X xFactory() {
//returns one of X permitted subtypes
}
// Maintenance domain B built against A 1.0
int z = switch (x) {
case A a: ...
case B b: ...
// no default
// boom
}
Given the fact that removal of a permitted subtype is also an
incompatible change (since either a public type is removed or it can no
longer be a subtype of the same sealed supertype) - it means the set of
permitted types has to be set in stone.
Exhaustiveness check is a double-edged sword: I wouldn't be surprised if
in a not-so-distant future we have JEPs similar to:
https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
Thanks,
Michal
On 15/04/2020 14:58:01, "Brian Goetz" <brian.goetz at oracle.com> wrote:
>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>
>><mailto: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