Dart Mixins

Reusing code across multiple classes

🔄 What are Mixins?

Mixins in Dart allow you to reuse code across multiple classes without inheritance. They provide a way to share functionality between classes that don't have a natural parent-child relationship.


// Mixin definition
mixin Flyable {
  void fly() => print('Flying high in the sky!');
}

// Using mixin with 'with' keyword
class Bird with Flyable {
  void chirp() => print('Chirp chirp!');
}
                                    

Key Mixin Concepts

🔄

Code Reuse

Share methods across multiple classes

mixin Swimmable {
  void swim() => print('Swimming!');
}
🔗

Multiple Mixins

Use multiple mixins in one class

class Duck with Flyable, Swimmable {}
🎯

No Instantiation

Mixins cannot be instantiated directly

// Flyable f = Flyable(); // Error!
📋

On Constraint

Restrict mixin usage to specific types

mixin Flyable on Animal {}

🔹 Basic Mixin Example

Here's how to create and use a simple mixin:

// Define mixins
mixin Walkable {
  void walk() => print('Walking on legs');
}

mixin Swimmable {
  void swim() => print('Swimming in water');
}

mixin Flyable {
  void fly() => print('Flying in the air');
}

// Use mixins in classes
class Human with Walkable, Swimmable {
  void speak() => print('Hello!');
}

class Fish with Swimmable {
  void breatheUnderwater() => print('Breathing through gills');
}

class Bird with Walkable, Flyable {
  void chirp() => print('Tweet tweet!');
}

void main() {
  Human human = Human();
  human.walk();    // Walking on legs
  human.swim();    // Swimming in water
  human.speak();   // Hello!
  
  Fish fish = Fish();
  fish.swim();     // Swimming in water
  fish.breatheUnderwater(); // Breathing through gills
  
  Bird bird = Bird();
  bird.walk();     // Walking on legs
  bird.fly();      // Flying in the air
  bird.chirp();    // Tweet tweet!
}

Output:

Walking on legs

Swimming in water

Hello!

Swimming in water

Breathing through gills

Walking on legs

Flying in the air

Tweet tweet!

🔹 Mixins with Properties

Mixins can also contain properties and getters:

mixin Identifiable {
  String _id = '';
  
  String get id => _id;
  
  void setId(String newId) {
    _id = newId;
  }
  
  void displayId() {
    print('ID: $_id');
  }
}

mixin Timestamped {
  DateTime? _createdAt;
  
  DateTime? get createdAt => _createdAt;
  
  void markCreated() {
    _createdAt = DateTime.now();
  }
  
  void showTimestamp() {
    if (_createdAt != null) {
      print('Created at: $_createdAt');
    }
  }
}

class User with Identifiable, Timestamped {
  String name;
  
  User(this.name) {
    setId('USER_${name.toUpperCase()}');
    markCreated();
  }
  
  void introduce() {
    print('Hi, I am $name');
    displayId();
    showTimestamp();
  }
}

void main() {
  User user = User('Alice');
  user.introduce();
  // Hi, I am Alice
  // ID: USER_ALICE
  // Created at: 2024-01-15 10:30:45.123456
}

Output:

Hi, I am Alice

ID: USER_ALICE

Created at: 2024-01-15 10:30:45.123456

🔹 Mixin with 'on' Constraint

Use 'on' to restrict which classes can use a mixin:

// Base class
class Animal {
  String name;
  Animal(this.name);
  
  void eat() => print('$name is eating');
}

// Mixin with constraint - can only be used on Animal or its subclasses
mixin Domesticated on Animal {
  String? owner;
  
  void setOwner(String ownerName) {
    owner = ownerName;
  }
  
  void showOwnership() {
    if (owner != null) {
      print('$name belongs to $owner');
    } else {
      print('$name has no owner');
    }
  }
}

class Dog extends Animal with Domesticated {
  Dog(String name) : super(name);
  
  void bark() => print('$name says Woof!');
}

class Cat extends Animal with Domesticated {
  Cat(String name) : super(name);
  
  void meow() => print('$name says Meow!');
}

void main() {
  Dog dog = Dog('Buddy');
  dog.setOwner('John');
  dog.bark();           // Buddy says Woof!
  dog.showOwnership();  // Buddy belongs to John
  
  Cat cat = Cat('Whiskers');
  cat.meow();           // Whiskers says Meow!
  cat.showOwnership();  // Whiskers has no owner
}

Output:

Buddy says Woof!

Buddy belongs to John

Whiskers says Meow!

Whiskers has no owner

🧠 Test Your Knowledge

Which keyword is used to apply a mixin to a class?