Introduction to Mixins
Part of the Object Oriented Programming section of Coddy's Dart journey — lesson 50 of 110.
You've learned that Dart only allows extending one class, and while you can implement multiple interfaces, you must write all the code yourself. But what if you want to share actual implementation code across multiple unrelated classes? This is where mixins come in.
A mixin is a way to reuse code in multiple class hierarchies. Think of it as a bundle of methods and properties that you can "mix into" any class, giving it new capabilities without using inheritance.
mixin Swimming {
void swim() {
print('Swimming through the water');
}
}
class Duck with Swimming {
void quack() {
print('Quack!');
}
}
class Fish with Swimming {
void blowBubbles() {
print('Blub blub');
}
}
void main() {
var duck = Duck();
duck.quack();
duck.swim(); // From the mixin
var fish = Fish();
fish.swim(); // Same implementation, different class
}Notice the with keyword - this is how you apply a mixin to a class. Unlike implements, you don't need to write the method yourself. The mixin provides the actual code, and your class gains that functionality automatically.
Mixins solve a real problem: Duck and Fish aren't related through inheritance, yet they both need swimming behavior. With mixins, you write the code once and share it wherever needed.
Challenge
EasyLet's build a musical instrument system that demonstrates how mixins let you share behavior across unrelated classes. You'll create a mixin that provides tuning functionality, then apply it to different instruments that aren't related through inheritance.
You'll organize your code into two files:
instruments.dart: Define your mixin and instrument classes here:- A
Tunablemixin with a methodtune()that printsTuning the instrument...and a methodcheckTuning()that printsTuning is perfect! - A
Guitarclass that uses theTunablemixin. Add aString brandproperty with a constructor. Include a methodstrum()that prints[brand] guitar strumming chords - A
Pianoclass that also uses theTunablemixin. Add anint keysproperty with a constructor. Include a methodplay()that printsPlaying [keys]-key piano
- A
main.dart: Import your instruments file and demonstrate how both unrelated instruments gain tuning capabilities from the same mixin:- Create a
Guitarwith brand'Fender' - Create a
Pianowith88keys - For the guitar: call
tune(), thenstrum(), thencheckTuning() - Print an empty line
- For the piano: call
tune(), thenplay(), thencheckTuning()
- Create a
Notice how Guitar and Piano are completely different instruments with no inheritance relationship, yet they both gain the exact same tuning methods from the Tunable mixin. You write the tuning code once, and both classes can use it with the with keyword.
Expected output:
Tuning the instrument...
Fender guitar strumming chords
Tuning is perfect!
Tuning the instrument...
Playing 88-key piano
Tuning is perfect!Cheat sheet
A mixin is a way to reuse code across multiple unrelated classes without using inheritance. It's a bundle of methods and properties that you can "mix into" any class.
Define a mixin using the mixin keyword:
mixin Swimming {
void swim() {
print('Swimming through the water');
}
}Apply a mixin to a class using the with keyword:
class Duck with Swimming {
void quack() {
print('Quack!');
}
}
class Fish with Swimming {
void blowBubbles() {
print('Blub blub');
}
}Unlike implements, you don't need to write the method implementation yourself - the mixin provides the actual code, and your class gains that functionality automatically.
Both Duck and Fish can now use the swim() method even though they aren't related through inheritance:
var duck = Duck();
duck.swim(); // From the mixin
var fish = Fish();
fish.swim(); // Same implementation, different classTry it yourself
import 'instruments.dart';
void main() {
// TODO: Create a Guitar with brand 'Fender'
// TODO: Create a Piano with 88 keys
// TODO: For the guitar: call tune(), then strum(), then checkTuning()
// TODO: Print an empty line
// TODO: For the piano: call tune(), then play(), then checkTuning()
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesLibraries & ImportsIntroduction to OOPClasses vs ObjectsThe this KeywordMethodsInstance VariablesConstructor BasicsRecap - Simple Calculator4Null Safety
Intro to Null SafetyNullable vs Non-NullableThe ? and ! OperatorsLate Keyword & Null SafetyNull-Aware OperatorsNull Safety in ClassesRecap - User Profile System7Abstract Classes & Interfaces
Abstract ClassesAbstract MethodsInterfaces in DartImplicit InterfacesImplementing vs ExtendingMultiple InterfacesRecap - Shape Calculator10Collections & Generics
List, Set, Map OverviewType-Safe CollectionsGeneric ClassesGeneric MethodsGeneric ConstraintsIterable & IteratorRecap - Generic Storage13Advanced OOP Concepts
Composition vs InheritanceExtension MethodsCallable ClassesSealed Classes (Dart 3)Records (Dart 3)Patterns & Matching (3.0)Enums with Methods16Project: Library Management
Project OverviewBook and User Classes2Constructors in Dart
Default ConstructorNamed ConstructorsInitializer ListsConstant ConstructorsFactory ConstructorsRedirecting ConstructorsRecap - Shape Builder5Encapsulation
Public vs Private MembersThe _ Prefix ConventionLibrary-Level PrivacyGetters & Setters DepthInformation HidingRecap - Student Records8Mixins
Introduction to MixinsCreating MixinsUsing Multiple Mixinson Keyword in MixinsMixin vs InheritanceMixin vs InterfaceRecap - Animal System11Special Methods
toString() OverridehashCode & == OverrideComparable Interfacecall() MethodnoSuchMethod OverrideRecap - Custom Collection14Design Patterns Part 1
Intro to Design PatternsSingleton PatternFactory PatternObserver PatternStrategy Pattern3Class Properties
Instance vs Static MembersFinal & Const FieldsLate VariablesStatic Methods & FieldsGetters and SettersRecap - Bank Account Manager6Inheritance
Basic InheritanceThe super KeywordMethod OverridingThe @override AnnotationThe final Class KeywordConstructors & InheritanceRecap - Employee Hierarchy9Polymorphism
Polymorphism BasicsPolymorphism via InterfacesRuntime Type CheckingThe is & as OperatorsCovariant KeywordRecap - Payment Processor