0

As a concrete example

sealed interface A permits B {
    default void a() {
        this.b();
    }
}
    
non-sealed interface B extends A {
    void b();
}

I know that this does not compile, but from a language perspective i don't understand what reason the compiler/compiler implementors would have to disallow it.

Ethan McCue
  • 883
  • 1
  • 8
  • 17
  • 2
    From the point of view of the compiler implementors, it's pretty easy: The rules of the language say it's an error, so the compiler must treat it as an error. Otherwise it wouldn't be a conformant implementation of the language. From the language designers' point of view, I suppose the question is rather what reason is there to allow it? Why add an exception to an otherwise perfectly consistent rule? What's the use case that would justify such an exception? – sepp2k Mar 07 '21 at 19:33

1 Answers1

3

As @sepp2k commented, there is an obvious answer: b() is not a member of A.

You are appealing to an intuition that says "sum types are sort of like union types" and "since b() is in the intersection of all known types in the union 'A=B or nothing else', then we should be able to treat b() as being a member of A". Besides "this just isn't how it works", consider how fragile such "duck typing" would be to changes in B, changes in the permits list of A, etc. And for what good reason?

If A wants to express a constraint that all its subclasses have a method b(), there is a long-standing way to do that: then A can declare an abstract b(). Introducing this sort of complexity in the language for the corner case of "sealed class with only one subclass" would be pretty silly, when there is a trivially easy and safer way to do it already. "But I would have to type one more line of code in A" is not a good reason to wish for this sort of magic.

Brian Goetz
  • 90,105
  • 23
  • 150
  • 161