Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A mixin in Dart is a mechanism for reusing state and behavior across multiple independent class hierarchies without relying on traditional single inheritance. It allows a class to incorporate the members of one or more mixins using the with keyword, injecting the mixin’s implementation directly into the class’s inheritance hierarchy.

Syntax and Declaration

A mixin is declared using the mixin keyword. It can contain both properties (state) and methods (behavior).
mixin Logger {
  String logPrefix = 'INFO:';

  void log(String message) {
    print('$logPrefix $message');
  }
}

class SystemService with Logger {
  void initialize() {
    log('System initialized.'); // Accesses the mixin's method
  }
}

Architectural Constraints

Mixins enforce specific compiler rules to maintain a predictable inheritance tree:
  1. No Instantiation: You cannot create an instance of a mixin directly (e.g., Logger() is invalid).
  2. No Generative Constructors: A mixin cannot declare any generative constructors. It relies entirely on the constructor of the class it is mixed into.
  3. Implicit Interfaces: Like classes, every mixin implicitly defines an interface. A class can implement a mixin’s interface without inheriting its implementation.

Type Restriction (on keyword)

You can restrict a mixin so it can only be applied to classes that extend or implement a specific type. This is done using the on keyword. Restricting a mixin allows the mixin’s internal code to safely invoke methods from the target superclass, utilizing the super keyword or direct method calls.
class EventHandler {
  void dispatchEvent() => print('Event dispatched');
}

// This mixin can ONLY be applied to subclasses of EventHandler
mixin Clickable on EventHandler {
  void click() {
    print('Clicked');
    dispatchEvent(); // Safely accesses EventHandler's method
  }
}

class Button extends EventHandler with Clickable {}

Linearization and Method Resolution Order

When a class applies multiple mixins, Dart resolves method conflicts using a process called linearization. Mixins are not evaluated concurrently; they are stacked sequentially in the order they are declared in the with clause. Dart creates intermediate, anonymous superclasses for each mixin. The mixin declared last (furthest to the right) forms the most derived superclass, meaning its methods will override identical methods from mixins declared earlier.
mixin A {
  void execute() => print('A executed');
}

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

class Task with A, B {}

void main() {
  final task = Task();
  task.execute(); // Outputs: "B executed"
}
In the example above, the inheritance chain is effectively: Object -> Object with A -> (Object with A) with B -> Task. Because B is applied last, its execute method shadows A’s.

The mixin class Modifier (Dart 3.0+)

By default, a mixin cannot be used as a standard class, and a standard class cannot be used as a mixin. To create a declaration that functions as both, Dart 3.0 introduced the mixin class modifier.
mixin class Equatable {
  bool isEqual(dynamic other) => true;
}

// Valid: Used as a mixin
class User with Equatable {}

// Valid: Used as a standard superclass
class Admin extends Equatable {}
A mixin class must adhere to the constraints of both constructs: it cannot have an on clause (as it must be capable of standing alone as a class), and it cannot declare a generative constructor (as it must be capable of being mixed in).
Master Dart with Deep Grasping Methodology!Learn More