|sealed interface Node { ... } |

    In this streamlined form, |Node| may be extended only by its
    nestmates. This may be suitable for many situations, but not for
    all; in this case, the user may specify an explicit |permits| list:

    |sealed interface Node permits FooNode, BarNode { ... } |

    The two forms may not be combined; if there is a permits list, it
    must list all the permitted subtypes. We can think of the simple
    form as merely inferring the |permits| clause from information in
    the same compilation unit.


what inferring from the same compilation unit means ?

It means: if there is no "permits" list, the compiler is allowed to synthesize one that contains exactly the list of subtypes declared in the same compilation unit.  (Much like the way we synthesize the NestMembers attribute.)


- it works for anonymous class declared in the same compilation unit ?

Anonymous classes are a good question.  On the one hand, I can imagine when they might be useful.  On the other, it means there's no way anyone -- including the current class, to which all the subtypes are accessible -- will be able to switch exhaustively over them.  I think we should consider banning them, as you can always fall back to a named class.  The exhaustiveness part is important, and too easy to forget about when you're writing the class.

(Other restrictions: classes in the permits list must be in the same module (or if not in a module, same package and protection domain) as the sealed type, and must be accessible to the sealed type.)

- it works for functional interface for lambda in the same compilation unit ?

Same as for anon classes; if we ban one, we ban the other.

  what exactly the permit list contains ??
  (dynamic nestmate/sealed class to the rescue ?)

I don't seen an interaction with dynamic nestmates.  The permits list is an explicit list; if the dynamic class is not on the list, it can't be a subtype, even if its in the nest.  If we infer the list, we're not recording "all nestmates", but instead inferring it to be the list of nestmates known at compile time.

  And in another compilation unit
    Fun fun = x -> 2 * x;   // rejected because Fun is sealed ?

Yep.


    /Note:/ It might be allowable for VM support to follow in a later
    version, rather than delaying the feature entirely.


Does seems to be a good idea to divorce the two. It means you can create classes with ASM that will work for a version of the VM but not the next one.

I think you mean "does not seem to be a good idea"?   I agree, it's got problems, such as the ones you raise.  But it is a possible move we can make, so we can keep it on the board until we have more visibility into the cost of waiting for VM support.



    *Accessibility.* Subtypes need not be as accessible as the sealed
    parent. In this case, clients are not going to get the chance to
    exhaustively switch over them; they’ll have to make these switches
    exhaustive with a |default| clause or other total pattern. When
    compiling a switch over such a sealed type, the compiler can
    provide a useful error message (“I know this is a sealed type, but
    I can’t provide full exhaustiveness checking here because you
    can’t see all the subtypes, so you still need a default.”)


Yes !
I expect a public sealed interface with several package private implementations to be a common pattern.

I agree qualitatively (and share your conclusion), but disagree with the quantitative statement here ("common").  I think it will be common _for platform and low-level library implementors_ to do this.  But if the feature is successful, this will probably be a tiny fraction of the sealed types in the world.  So yes, this is an important pattern, but I hope it is UNcommon.

The implication is that you can not define (at least now) the implementations inside the sealed interface because all class members of an interface can only be public so you can not declare a package-private implementation.  I don't know exactly why private class are not allowed in interface, it seems to be an overlook for me.

Yes, this (and fields too, even though they kind of suck in interfaces), was largely overlooked.  We are gathering a list of "gratuitous nesting constraints", of which this is one, and at some point will bang them all out.  (Restrictions on static members in nested classes is another.  Local interfaces and enums is another. Maybe even local methods.  Etc.)


Reply via email to