Description
Comments on https://github.com/dart-lang/language/blob/master/working/modules/feature-specification.md
The grammar declarations contain:
classDeclaration ::= 'open'? 'interface'? 'mixin'? 'class' // ...
mixinDeclaration ::= 'open'? 'interface'? 'mixin' // ...
I do not want to conflate mixins and classes. Those are two separate kinds of declarations, and I would very much like to get rid of the current ability to mix in classes (q.v. #1643). If the mixin class
is intended to support the current mixin-able classes, I'd just remove it and not allow that. If we touch this area, that's a very good time to remove the ability to mix in classes entirely. (Any time is a good time IMO, the best time would be yesterday!)
I'm also not sure it makes sense to extend a mixin declaration.
Not yet, at least, we don't have composite mixins, and you can't do extends mixin
anyway. I'd remove the 'open'?
from mixinDeclaration
for now, writing open
in front doesn't mean anything unless we add the ability to actually extend them.
(Unless lacking open
would mean that you cannot extend something mixing in the mixin. I'm not sure that's a good idea, but it would be consistent. We'd then need a different word if we ever introduce composite mixin declarations, so I think I'd prefer to reserve open
for that).
That means that anywhere later where it talks about instantiating mixins, or mixins having generative constructors (any constructors, really), it should be dropped. Mixins do not have constructors, and cannot be instantiated.
(I also think abstract interface class
should be a possibility, cannot instantiate, can extend or implement).
Like slightly later where it states:
- It is a compile-time error to invoke a generative constructor of a type if the type defines or inherits any unimplemented abstract members. You can directly construct anything internally if it wouldn't cause a problem to do so, even an interface or an abstract class. TODO: Even a mixin?
You can't instantiate a mixin declaration. It must be mixed onto a superclass before it even becomes a class, which is what can be instantiated. While we still, effectively, have mixin class
declarations, it's the class you are instantiating, not the mixin which can be derived from it.
(The usual model for the first sentence is to say:
- It's a compile-time error to invoke a generative constructor of a class if the class does not have a valid implementation for all members of its interface.
So, don't look at declarations, look at implementation vs interface. We might need another name for "interface" if we have classes without an interface, they still have a signature, just not one you can implements
).
And much later:
- It is a compile-time error if a public-named type marked mixin defines any constructors. TODO: Is this restriction correct?
Yes, it's currently correct. We could allow factory constructors (we do allow static methods, and factory constructors are basically static methods with trickier type parameters and a fixed return type), and with interface mixin
declarations we might want to allow factory constructors.
If we allow any use "internally", but only declared uses externally, then it does become an issue that we separate mixins and class declarations.
You cannot do interface Foo { ... }
and use it as a mixin, because it is not a mixin and you can't mix-in non-mixins (please, do not allow that!). But if you write interface mixin Foo { ... }
then the type is publicly a mixin.
Instead of allowing you to internally ignore any constraints, should we instead allow you to declare something as interface _mixin
where it's only privately a mixin?
About:
Capabilities on legacy classes
The above syntax means that it an error to implement, mixin, or extend a class declared just using class. This would break nearly all existing Dart code. To avoid that, we specify that Dart classes that are not in modules are implicitly treated as if they were declared as
open interface mixin class
.
That sounds like an implicit language versioning. Why not just use explicit language versioning, and migrate existing code by adding open interface
in front of all classes, and maybe combine with #1643 to migrate code extending a "mixin class
" to with Name
instead of extends Name
.
(Might be worth mentioning that you can make non-extensible classes today by not exposing a public generative constructor.)