mixin declares a reusable block of methods that no class instantiates on its own. A class composes mixins with class C with M1, M2, gaining their methods as if it had declared them. Mixins add behavior, not stored state.

Program

Play the program to call a method that chains through two composed mixins.

mixins.dart
Replay: real traced execution (multi-file project)
mixin Greetable {
  String greet(String name) => 'Hello, $name';
}

mixin Loud {
  String shout(String msg) => '${msg.toUpperCase()}!';
}

class Bot with Greetable, Loud {
  String announce(String name) => shout(greet(name));
}

void main() {
  var b = Bot();
  print(b.announce('Ada'));
}
  1. b ← Bot instance

    13void main() {14  var b = Bot();15  print(b.announce('Ada'));
    values this stepBot instanceb
  2. call ← b.announce('Ada')

    14  var b = Bot();15  print(b.announce('Ada'));16}
    values this stepb.announce('Ada')callBot instanceb
  3. calls ← shout(greet('Ada'))

    9class Bot with Greetable, Loud {10  String announce(String name) => shout(greet(name));11}
    values this stepshout(greet('Ada'))callsAdaname
  4. return value ← Hello, Ada

    1mixin Greetable {2  String greet(String name) => 'Hello, $name';3}
    values this stepHello, Adareturn valueAdaname
  5. return value ← HELLO, ADA!

    5mixin Loud {6  String shout(String msg) => '${msg.toUpperCase()}!';7}
    values this stepHELLO, ADA!return valueHello, Adamsg
  6. return value ← HELLO, ADA!

    9class Bot with Greetable, Loud {10  String announce(String name) => shout(greet(name));11}
    values this stepHELLO, ADA!return value
  7. print(b.announce('Ada'));

    14  var b = Bot();15  print(b.announce('Ada'));16}
    outputHELLO, ADA!
mixin `mixin Greetable { ... }` declares reusable methods; a mixin cannot be instantiated on its own.
with `class Bot with Greetable, Loud` composes both mixins so their methods belong to `Bot`.
composition over inheritance Mixins add behavior without sharing state or forcing a single inheritance chain.