flutter
/

Dart Mixins – Reusing Code Across Class Hierarchies

Last Sync: Today

On this page

11
0%
5 min read
Remaining
5 minleft

Click any section to jump — progress syncs automatically

flutter

Dart Mixins – Reusing Code Across Class Hierarchies

What are Mixins?

Mixins are a way to reuse code across multiple class hierarchies without using inheritance. A mixin defines a set of methods and properties that can be added to any class. This is particularly useful when you want to share behavior between classes that are not otherwise related. Dart supports mixins through the mixin keyword and the with clause.

Creating a Mixin

You define a mixin using the mixin keyword, followed by a name and a body containing methods and fields you want to reuse. Mixins cannot have constructors (they are not meant to be instantiated alone).

DARTRead-only
1
mixin CanFly {
  void fly() {
    print('Flying...');
  }
}

mixin CanSwim {
  void swim() {
    print('Swimming...');
  }
}

Using Mixins with with

To add one or more mixins to a class, use the with keyword followed by the mixin names. The class then inherits all the methods and fields from those mixins.

DARTRead-only
1
class Bird with CanFly {}

class Fish with CanSwim {}

class Duck with CanFly, CanSwim {} // multiple mixins

void main() {
  var duck = Duck();
  duck.fly();   // Flying...
  duck.swim();  // Swimming...
}

Mixin Syntax and Restrictions

Mixins have some important restrictions:

    • A mixin cannot have a constructor (it is not a class).
    • A mixin cannot extend any class, though it can use the on keyword to restrict the types that can use it (see below).
    • Prior to Dart 2.12, mixins could only be created from classes with no constructors and no super calls. Now, with the mixin keyword, these restrictions are explicit.

Multiple Mixins and Method Conflicts

When you apply multiple mixins that define the same method, the last mixin in the with list overrides earlier ones. If a class itself defines the method, it overrides all mixin versions.

DARTRead-only
1
mixin A {
  void foo() => print('A');
}

mixin B {
  void foo() => print('B');
}

class MyClass with A, B {}

void main() {
  MyClass().foo(); // prints 'B' (last mixin wins)
}

Mixins vs Inheritance vs Interfaces

    • Inheritance (extends): Creates an 'is‑a' relationship, and you get implementation. A class can extend only one superclass.
    • Interfaces (implements): Enforces a contract but gives no implementation. A class can implement multiple interfaces.
    • Mixins (with): Gives you implementation without the 'is‑a' relationship. A class can use multiple mixins.

The on Keyword (Constraining Mixin Usage)

You can restrict a mixin to be used only on classes that extend a certain type. This is done with the on keyword. This allows the mixin to call methods on super that are guaranteed to exist.

DARTRead-only
1
class Animal {
  void breathe() => print('Breathing...');
}

mixin Walker on Animal {
  void walk() {
    breathe(); // safe because mixin can only be used on Animal subtypes
    print('Walking...');
  }
}

class Dog extends Animal with Walker {}

// class Fish with Walker {} // Error: Fish does not extend Animal

Mixins and Constructors

Mixins cannot have constructors. If a mixin needs initialization, it can define fields that must be initialized by the class using it. For example, you can define a getter that requires a value to be present.

DARTRead-only
1
mixin HasName {
  String get name;
  void greet() => print('Hello, my name is $name');
}

class Person with HasName {
  @override
  final String name;
  Person(this.name);
}

void main() {
  Person('Alice').greet(); // Hello, my name is Alice
}

Best Practices

    • Use mixins when you need to share behavior across unrelated classes.
    • Keep mixins focused on a single responsibility (like a trait).
    • Avoid defining fields in mixins unless they are abstract and require the using class to provide them.
    • Use the on keyword to document and enforce the required superclass type.
    • Be mindful of method name conflicts; order mixins deliberately.

Complete Example

DARTRead-only
1
mixin Logger {
  void log(String message) {
    print('[LOG] $message');
  }
}

mixin Timestamp {
  DateTime get now => DateTime.now();
}

class NetworkService with Logger, Timestamp {
  void fetchData() {
    log('${now}: Fetching data...');
    // fetch logic
  }
}

class DatabaseService with Logger {
  void query() {
    log('Querying database...');
  }
}

void main() {
  var net = NetworkService();
  net.fetchData();

  var db = DatabaseService();
  db.query();
}

Key Takeaways

    • Mixins (defined with mixin) allow you to reuse code across unrelated classes.
    • Use the with keyword to apply one or more mixins to a class.
    • Mixins cannot have constructors and can use on to restrict usage to subtypes of a given class.
    • Method conflicts are resolved by the order of mixins (last wins).
    • Mixins provide a flexible alternative to multiple inheritance.

Try it yourself

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

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

class Duck with Flyable, Swimmable {}

void main() {
  var duck = Duck();
  duck.fly();
  duck.swim();
}

Test Your Knowledge

Q1
of 4

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

A
extends
B
implements
C
with
D
mixin
Q2
of 4

What keyword is used to define a mixin?

A
class
B
mixin
C
interface
D
trait
Q3
of 4

Can a mixin have a constructor?

A
Yes
B
No
C
Only if it's abstract
D
Only with the `factory` keyword
Q4
of 4

What does the `on` keyword in a mixin declaration do?

A
Specifies that the mixin can only be used on classes that extend a given type
B
Adds logging to the mixin
C
Makes the mixin abstract
D
Allows the mixin to have constructors

Frequently Asked Questions

What is the difference between a mixin and an abstract class?

An abstract class can be extended and can have constructors; a mixin cannot be instantiated and is meant to be used with with. Mixins are a way to compose behavior, while abstract classes are more about defining a common base type.

Can a mixin have fields?

Yes, a mixin can have instance fields, but they will be added to every class that uses the mixin. However, fields are not inherited; they are physically copied into the class. This can lead to duplication if used heavily, so prefer methods or abstract getters.

Can I use a class as a mixin?

Yes, in older Dart versions, any class with a no‑argument constructor and no super calls could be used as a mixin. With the mixin keyword, it's clearer. However, you can still apply a class as a mixin (though it's discouraged – better to define a dedicated mixin).

What does the `on` keyword do in a mixin?

It restricts which classes can use the mixin. The mixin can only be applied to classes that extend (or implement) the type specified after on. This allows the mixin to safely call methods on super.

How does Dart resolve conflicts when two mixins define the same method?

The order of mixins matters. The last mixin in the with list overrides earlier ones. If the class itself defines the method, it overrides all mixin versions.

Can I use a mixin without the `mixin` keyword?

Before Dart 2.12, you could use a class as a mixin if it met certain restrictions. The modern way is to use the mixin keyword, which makes the intent clear and enforces restrictions.

Previous

dart encapsulation

Next

dart interfaces

Related Content

Need help?

Explore our comprehensive docs or start a chat with our tech experts.