Sealed types

Brian Goetz brian.goetz at oracle.com
Sat Dec 1 13:26:03 UTC 2018


>         - 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. 
>
>
> Exhaustiveness is one consequence of a sealed interface, but having a 
> sealed interface, i.e. constraining all subtypes to be defined in the 
> same compilation unit is useful even without exhaustiveness.
> It's a way to allow to make an interface visible without having to 
> care about implementations you do not know.
>
> In a previous mail, you said that if an implementation class is not 
> visible from a switch, then the compiler will just ask for a default.
> An anonymous class (or a local class of a method for completeness) is 
> just a class which is not visible from any switches.

This is all obviously true, but also a kind of false equivalency. Yes, 
constraint can useful without exhaustiveness.  But, if you make it too 
easy to undermine exhaustiveness, people will do this without realizing 
it, and likely for little benefit.  It is really really common that when 
declaring APIs, users forget about what problems they are creating for 
their callers.  Examples include:
  - "Why can't I declare defaults for Object methods" 
(https://stackoverflow.com/questions/24016962/java8-why-is-it-forbidden-to-define-a-default-method-for-a-method-from-java-lan/24026292#24026292) 
-- because you'd break subclasses.
  - "Why can't default methods be synchronized" 
(https://stackoverflow.com/questions/23453568/what-is-the-reason-why-synchronized-is-not-allowed-in-java-8-interface-methods?noredirect=1&lq=1) 
-- because it doesn't mean what you think it means.
  - Use-site ambiguity overload errors resulting from overloads like 
m(Function) and m(Predicate) -- because then you create an API that no 
client can use it with lambdas, oops.

In each of these cases, the problem is a failure to consider what the 
impact of the declaration-site decisions are on callers.  So, I think 
the question of anonymous classes is more subtle than you're giving it 
credit for.

So yes, accessibility can undermine exhaustiveness -- outside the 
capsule.  (Inside the capsule, you still get exhaustiveness.)  But I see 
no reason why we should leap from "yes, sometimes it fails" to "so let's 
make it really easy to make it fail all the time."


>
> For me, a sealed type and all its implementation are nestmates from 
> the VM point of view (it's stronger that you are proposing), they are 
> part of the same compilation unit.

Then we cannot allow subtypes outside the nest, because that would be in 
conflict with the nestmate design.  That's a possible point in the 
design space, but I think its overly restrictive, and eliminates some 
really important use cases.  Plus, only .001% of Java developers even 
know what a nest is, so it seems a little questionable to distort a 
programming model feature to match a VM feature that no one is aware of.

>
> see above, if we allow anonymous class, we have to allow lambdas (we 
> already support refactoring from one to the other).
> Given that the class of a lambda is only knows at runtime, it means 
> that the nestmate attributes and the sealed attributes have to be 
> updated at runtime.

A further argument that trying to say "sealing == nestmates" is pushing 
on the wrong end of the lever.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20181201/70b8627d/attachment-0001.html>


More information about the amber-spec-experts mailing list