Mixin vs Inheritance
Part of the Object Oriented Programming section of Coddy's Dart journey — lesson 54 of 110.
Now that you've learned how mixins work, let's clarify when to use them instead of inheritance. The key difference lies in the relationship they express.
Inheritance represents an "is-a" relationship. A Dog is an Animal. The subclass is a specialized version of the parent, and you can only extend one class.
Mixins, on the other hand, represent a "can-do" relationship. A Dog can swim, but swimming isn't what defines a dog.
// Inheritance: Dog IS an Animal
class Animal {
String name;
Animal(this.name);
}
class Dog extends Animal {
Dog(String name) : super(name);
}
// Mixin: Dog CAN swim (but isn't defined by swimming)
mixin Swimming {
void swim() => print('Swimming');
}
class Dog extends Animal with Swimming {
Dog(String name) : super(name);
}Use inheritance when classes share a fundamental identity and you need constructors in the parent. Use mixins when you want to add capabilities to classes that don't share a common ancestor.
| Feature | Inheritance | Mixin |
|---|---|---|
| Relationship | is-a | can-do |
| Limit | One parent only | Multiple mixins |
| Constructors | Allowed | Not allowed |
| Use case | Specialization | Shared behavior |
The best part? You can combine both - extend one class and mix in multiple capabilities, giving your classes exactly the features they need.
Challenge
EasyLet's build a worker system that demonstrates when to use inheritance versus mixins. You'll create a base class for the "is-a" relationship and mixins for "can-do" capabilities, then combine them to show how both approaches work together.
You'll organize your code into three files:
worker.dart: Define your base class that establishes the core identity of all workers:- A
Workerclass withString nameandString departmentproperties. Include a constructor that takes both values. Add a methodintroduce()that prints[name] works in [department]
- A
skills.dart: Define mixins that represent capabilities workers can have (the "can-do" relationships):- A
CanCodemixin with a methodwriteCode()that printsWriting code... - A
CanDesignmixin with a methodcreateDesign()that printsCreating design... - A
CanManagemixin with a methodleadTeam()that printsLeading the team...
- A
main.dart: Import both files and create specialized worker types that combine inheritance with mixins:- A
Developerclass that extendsWorkerand uses theCanCodemixin - A
TechLeadclass that extendsWorkerand uses bothCanCodeandCanManagemixins - Create a
Developernamed'Alice'in department'Engineering' - Create a
TechLeadnamed'Bob'in department'Engineering' - For Alice: call
introduce()thenwriteCode() - Print an empty line
- For Bob: call
introduce(), thenwriteCode(), thenleadTeam()
- A
Notice how both Developer and TechLead are workers (inheritance), but they can do different things (mixins). The TechLead combines multiple capabilities without needing multiple inheritance.
Expected output:
Alice works in Engineering
Writing code...
Bob works in Engineering
Writing code...
Leading the team...Cheat sheet
Inheritance represents an "is-a" relationship (a subclass is a specialized version of the parent), while mixins represent a "can-do" relationship (adding capabilities without defining identity).
// Inheritance: Dog IS an Animal
class Animal {
String name;
Animal(this.name);
}
class Dog extends Animal {
Dog(String name) : super(name);
}
// Mixin: Dog CAN swim
mixin Swimming {
void swim() => print('Swimming');
}
class Dog extends Animal with Swimming {
Dog(String name) : super(name);
}| Feature | Inheritance | Mixin |
|---|---|---|
| Relationship | is-a | can-do |
| Limit | One parent only | Multiple mixins |
| Constructors | Allowed | Not allowed |
| Use case | Specialization | Shared behavior |
You can combine both approaches - extend one class and mix in multiple capabilities:
class TechLead extends Worker with CanCode, CanManage {
TechLead(String name, String department) : super(name, department);
}Try it yourself
import 'worker.dart';
import 'skills.dart';
// TODO: Create a Developer class that extends Worker and uses the CanCode mixin
// TODO: Create a TechLead class that extends Worker and uses both CanCode and CanManage mixins
void main() {
// TODO: Create a Developer named 'Alice' in department 'Engineering'
// TODO: Call introduce() then writeCode() for Alice
// TODO: Print an empty line
// TODO: Create a TechLead named 'Bob' in department 'Engineering'
// TODO: Call introduce(), writeCode(), then leadTeam() for Bob
}
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