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 <brian.go...@oracle.com> 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.