Description
(branched off #31 (comment))
Goal
Migrate all mixins (not only super-mixins) to the new mixin
syntax.
Background
Classes that were meant to be super-mixins already had restrictions matching those of the new mixin
keyword. This makes the migration from class
to mixin
for super-mixins simple. That's not the case for non-super-mixins. Those classes are extended, implemented, and mixed in in the wild. Therefore changing what previously was declared as a class
to a mixin
breaks classes that used extends
instead of with
.
Proposal: temporarily allow extending mixins
- It does not require migration of any code that uses mixins, only code that defines mixins
extends
andwith
have no semantic differences observable by the developer- It does not conflict with the new
mixin
semantics
Beyond that, this allows us to remove the ability to derive a mixin as a non-breaking change. To do that we will have to overload what extends
means.
Imagine this declaration:
class Foo extends Bar
The compiler first checks whether Bar
is a mixin
or a class
.
If Bar
is a mixin
, then the compiler desugars the above declaration into:
class Foo extends Object with Bar
More generally, class Foo extends M1 with M2, ..., Mk
desugars into class Foo extends Object with M1, M2, ..., Mk
.
If Bar
is a class
, then it's a normal derivation. The lint prefer_mixin
then can be used to help authors find classes used as mixins and convert them to mixin
syntax without breaking their users.
This approach will allow converting the vast majority of mixins present in the Dart ecosystem to the new mixin
syntax without breaking existing user code. For example, Flutter can update abstract class WidgetsBindingObserver
to mixin WidgetsBindingObserver
as a non-breaking change.
Changing from class
to mixin
still comes with mixin
restrictions, just like new mixin proposal wants, such as:
- mixins cannot extend other classes
- mixins cannot have constructors and factories
- mixins cannot be instantiated directly
These properties will protect mixin authors from accidentally breaking their users.
Discussions elsewhere
This topic was discussed on these other threads:
- use WidgetsBindingObserver as a mixin flutter/plugins#797
- Enforce that WidgetsBindingObserver is only used as a mixin or interface flutter/flutter#22290
- Is
mixin
for non-supermixins a good idea? #33
Updates
- Added a "Goal" section
- Removed argument that
A extends M
is simpler syntactically due to existence ofA with M
- Created a section with links to other discussions