Menu
Coddy logo textTech

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 icon

Challenge

Easy

Let'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 Tunable mixin with a method tune() that prints Tuning the instrument... and a method checkTuning() that prints Tuning is perfect!
    • A Guitar class that uses the Tunable mixin. Add a String brand property with a constructor. Include a method strum() that prints [brand] guitar strumming chords
    • A Piano class that also uses the Tunable mixin. Add an int keys property with a constructor. Include a method play() that prints Playing [keys]-key piano
  • main.dart: Import your instruments file and demonstrate how both unrelated instruments gain tuning capabilities from the same mixin:
    • Create a Guitar with brand 'Fender'
    • Create a Piano with 88 keys
    • For the guitar: call tune(), then strum(), then checkTuning()
    • Print an empty line
    • For the piano: call tune(), then play(), then checkTuning()

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 class

Try 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()
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming