Mixins: Sharing Behavior Across Class Trees
Suppose several kinds of animals can all swim. You could write a swim method in every animal class, but that means copying the same code again and again. A mixin solves this. A mixin is a small bundle of methods and fields that you can add to many classes without making them related by inheritance.
In Dart, you define a mixin with the mixin keyword, and you add it to a class with the with keyword.
mixin Swimmer {
void swim() => print('Paddling through the water!');
}
mixin Flyer {
void fly() => print('Up, up, and away!');
}
class Duck with Swimmer, Flyer {}
class Fish with Swimmer {}
void main() {
final duck = Duck();
duck.swim();
duck.fly();
final fish = Fish();
fish.swim();
}Here Duck can both swim and fly, while Fish only swims. Neither class had to copy any code.
Mixins versus inheritance
Inheritance (the extends keyword) gives a class everything from one parent. It answers the question "what is this?" A Duck is a Bird.
Mixins answer a different question: "what can this do?" A duck can swim, a fish can swim, but ducks and fish live on different branches of the class tree. Mixins let abilities cut across those branches.
Think of it this way:
Show diagram source
classDiagram
class Animal
class Bird
class Fish
class Duck
Animal <|-- Bird
Animal <|-- Fish
Bird <|-- Duck
Swimmer ..> Fish
Swimmer ..> Duck
Flyer ..> DuckA few helpful details
- A class can use several mixins:
class Duck with Swimmer, Flyer. If two mixins define the same method, the one listed last wins. - A mixin can depend on other members. Writing
mixin Swimmer on Animalsays the mixin may only be added to classes that extendAnimal, so it can safely callAnimal's methods. - Mixins can also use
extends-free helper state, like fields and getters, just like a normal class.
mixin Greeter {
String get name;
void greet() => print('Hi, I am $name.');
}
class Robot with Greeter {
@override
String get name => 'Rover';
}
void main() => Robot().greet();When to reach for a mixin
- The behavior is a small, reusable ability (
Comparable, logging, formatting). - The classes that need it do not share a sensible parent.
- You want to combine several abilities freely.
If two classes are truly the same kind of thing, use inheritance. If they merely share a job, use a mixin.
callout tip Mixins in Dart appear everywhere in real projects and frameworks, especially for UI code. Recognizing the with keyword is the key reading skill; writing your own small mixin is the key writing skill. endcallout
exercise Q: In class Penguin with Swimmer, Flyer {}, could you swap the order of the mixins and change the program's behavior? A: Not here, because Swimmer and Flyer define different methods with no overlap. Order only matters when two mixins supply the same member name; then the mixin listed last wins. endexercise
estimate minutes: 20 endestimate
Spotted a mistake, or code that does not work?