I would like to be able to declare a set of members that define a type without defining a class. I want this type to be usable in the implements clause of classes and mixins, and in the on clause of mixins and extensions, and, obviously, as a type annotation, but it should not be possible to extend or mixin an interface. Interfaces should be allowed to implement other interfaces, but should not be allowed to extend or mixin any classes.
In my mind, the cleanest syntax for doing this would be to use the builtin identifier interface to introduce a declaration similar to, but more limited than, a class declaration. The grammar could probably be improved, but would look something like this:
<interfaceDeclaration> ::= 'interface' <identifier> <typeParameters>? <interfaces>?
'{' (<metadata> <interfaceMemberDeclaration>)* '}'
where <interfaceMemberDeclaration> would allow methods (including getters, setters and operators) without any bodies.
I would suggest disallowing fields in order to make it clear that interfaces can't introduce fields into the types that implement them.
You can currently make an abstract class with a private generative constructor. That should introduce an interface and prohibit any mxin/extension use. (A class declaring a constructor cannot be used as a mixin, a class with no accessible generative constructor cannot be extended).
It would be nice to not have to write the constructor, which only exists for secondary, technical reasons, not because you actually want a constructor, and an interface declaration would achieve that.
I assume that an interface declaration would not be allowed to have non-abstract instance members (unless we get interface default methods). Since it's impossible to ever invoke the method implementation, it's guaranteed to be dead code.
That would also prevent field (instance variable) declarations (until we get abstract instance variable declarations).
Long ago, the language team had a discussion about approximately 4 bits of "permissions" for a class:
extends.with.implements, on with extensions/mixins, usages as a type.We can disable instance creation with abstract, but we can't specify the other permissions (or deny them) declaratively. Some combinations are not very useful, and it may be too verbose to specify the bits separately (abstract class C ... deny extends, deny with, deny implements {}), so we may want to package certain combinations using special keywords (like interface which would imply deny extends, deny with).
The idea that an interface I should not be able to extend a class is new. At first, it wouldn't make a difference (because no instance and no subclass of I can be created, so nobody can ever observe any implementations associated with I).
But if we add in the notion of 'interface default members' (which are automatically mixed into any concrete class implementing I but not implementing the given member) then it would be useful to be able to add implementations to the interface using extends or with, such that the interface default method implementations wouldn't have to be duplicated textually in the case where they can be obtained using extends or with.
So we might end up with a handful of special concepts like interface, but we should at least keep in mind what they are in terms of those orthogonal "permission bits", and notice whether we cover all and only the combinations that we really want for each special concept.
Most helpful comment
Long ago, the language team had a discussion about approximately 4 bits of "permissions" for a class:
extends.with.implements,onwith extensions/mixins, usages as a type.We can disable instance creation with
abstract, but we can't specify the other permissions (or deny them) declaratively. Some combinations are not very useful, and it may be too verbose to specify the bits separately (abstract class C ... deny extends, deny with, deny implements {}), so we may want to package certain combinations using special keywords (likeinterfacewhich would implydeny extends, deny with).The idea that an interface
Ishould not be able to extend a class is new. At first, it wouldn't make a difference (because no instance and no subclass ofIcan be created, so nobody can ever observe any implementations associated withI).But if we add in the notion of 'interface default members' (which are automatically mixed into any concrete class implementing
Ibut not implementing the given member) then it would be useful to be able to add implementations to the interface usingextendsorwith, such that the interface default method implementations wouldn't have to be duplicated textually in the case where they can be obtained usingextendsorwith.So we might end up with a handful of special concepts like
interface, but we should at least keep in mind what they are in terms of those orthogonal "permission bits", and notice whether we cover all and only the combinations that we really want for each special concept.