Seems like a reasonable proposal.
> sealed interface WithCheese __refines Sandwich { }
Would `_refines` operate at compile time with javac copy/pasting the
sealed list from Sandwich into WithCheese? An alternative is some new
classfile info to tell the VM to do the copy/paste at classload. Both
are possible but the VM option is more expensive to implement.
--Dan
On Thu, Apr 1, 2021 at 9:24 AM Brian Goetz <[email protected]> wrote:
>
> Been working with sealed classes a lot lately, and have run into a pattern
> that we might want to consider supporting more directly, which is interfaces
> that exist solely to refine a sealed class or interface. Suppose we have:
>
> sealed abstract class Sandwich { }
>
> interface WithCheese { }
> interface Toasted { }
> interface NontraditionalStructure { }
> interface NontraditionalIngredients { }
>
> class Cheeseburger extends Sandwich implements WithCheese { }
>
> class TunaMelt extends Sandwich implements Toasted, WithCheese { }
>
> class Burrito extends Sandwich implements WithCheese,
> NontraditionalStructure { }
>
> class ChipButty extends Sandwich implements NontraditionalIngredients { }
>
> class PopTart extends Sandwich implements NontraditionalIngredients,
> NonTraditionalStructure { }
>
> (see, e.g., https://twitter.com/matttomic/status/859117370455060481, for
> those who don't get the joke.)
>
> The constraint we would like to express here is that the interfaces
> WithCheese and Toasted exist to serve Sandwich, which is
> extension-controlled. To capture this, we also seal these interfaces, but
> now have to redundantly enumerate their subtypes. This is annoying and
> brittle, because we're stating it indirectly; a more direct capture of intent
> would be to say "Toasted can only be used with Sandwich."
>
> Even if Sandwich were an interface, and then we can say "Toasted extends
> Sandwich", we still have to redundantly enumerate the subtypes. If this game
> is about Sandwich, just having Sandwich enumerate its subtypes should be
> enough.
>
> Without trying to paint the bikeshed, this is a pretty simple extension to
> sealing:
>
> sealed interface WithCheese __refines Sandwich { }
>
> This says that WithCheese is sealed to either classes that extend Sandwich,
> or other interfaces that __refines Sandwich. As a bonus, default methods in
> WithCheese can refer to methods in Sandwich, since it must always be the case
> that `this instanceof Sandwich`.
>
> Essentially, I want to put the `permits` list on Sandwich, and have
> `WithCheese` and friends delegate their permits to `Sandwich`, rather than
> having each interface enumerate their subtypes.