Flutter uses mixins heavily, such as TickerProviderStateMixin and ChangeNotifier, and they solve multiple-inheritance needs.
A mixin is a bundle of fields and methods that can be added to many classes without inheritance:
mixin Logger {
void log(String msg) => print('[$runtimeType] $msg');
}
class Service with Logger { }A class lists mixins after with, optionally after extends: class Bird extends Animal with Flying, Singing. The mixins are applied left to right, each layered on top of the previous one, so a later mixin can override a method from an earlier one and reach it through super. This linearization is how Dart avoids the diamond problem.
Restrict where a mixin can be used with on: mixin Walker on Animal can only be applied to subclasses of Animal, and inside it you can call Animal's members and super.
Mixins can't have generative constructors. Since Dart 3, a class can only be used as a mixin if declared with mixin or mixin class (the latter is usable both as a normal class and a mixin).
In Flutter you'll write class _MyState extends State<MyWidget> with SingleTickerProviderStateMixin to give a state object the ability to drive animations, and models often use with ChangeNotifier or extends ChangeNotifier.
Prefer mixins for small, orthogonal capabilities. If you find a mixin needing lots of state from its host, composition (a field holding a helper object) may be clearer.
Example
abstract class Animal {
String get name;
String move() => '$name moves';
}
mixin Swimmer on Animal {
@override
String move() => '${super.move()} and swims';
}
mixin Flyer on Animal {
@override
String move() => '${super.move()} and flies';
int altitude = 0;
}
class Duck extends Animal with Swimmer, Flyer {
@override
String get name => 'Duck';
}
void main() {
final d = Duck()..altitude = 30;
print(d.move()); // Duck moves and swims and flies
print(d is Swimmer); // true
print(d.altitude); // 30
}Remember
with A, Blayers mixins left to right; later ones override earlier onesmixin M on Baserestricts use and allowssupercalls- Mixins have no constructors; declare with
mixinormixin class
Watch out for
- Relying on mixin order without realizing a later mixin silently overrides an earlier method.