skip to content

Mixins & Linearization

Mixins add members to a class through with, can require a superclass with on, and stack in a linear order that decides what super calls. Interviewers use them to test reuse without inheritance.

part ofDartoverview, primer and where to startread it →
on this pageshow

explore

questions

5

In Dart, what is a mixin, how do you declare one and apply it with `with`, and what can it contain?

level: juniorimportance: must knowfreq 65%

answer

  1. reuse without a superclass
  2. mixin keyword, then with
  3. fields and methods, no constructor
  4. abstract getter asks the host
  5. several mixins, comma-separated

basics

~20 s

A Dart mixin is a mixin declaration whose fields and methods are added to a class listed after with. It cannot be instantiated or declare a constructor, and one class can apply several mixins alongside its single superclass.

solid answer

~40 s

A mixin is a bundle of members declared with the `mixin` keyword and applied with `with`, for example `class UserApi with Logging`. It may hold instance fields, concrete methods, getters and abstract members; the class that applies it gets all of them and becomes a subtype of the mixin, so `UserApi() is Logging` is true. A mixin has no `extends` clause, cannot be constructed on its own and cannot declare a constructor, so any value it needs from its host comes through an abstract member such as `String get logTag;` that the class must implement. A class keeps exactly one superclass but may list several mixins: `class OrderApi extends BaseApi with Logging, Metrics`.

code

dart · 20 lines
dart
mixin Logging {
  String get logTag;

  void log(String message) => print('[$logTag] $message');
}

class UserApi with Logging {
  @override
  final String logTag = 'UserApi';

  Future<void> fetchUser(String id) async {
    log('GET /users/$id');
  }
}

void main() {
  final api = UserApi();
  api.fetchUser('42'); // [UserApi] GET /users/42
  print(api is Logging); // true
}

go deeper

for a junior

Recall the mixin keyword, the with keyword after extends, and that a mixin adds members without becoming the superclass. Know that it cannot be constructed.

for a middle

Explain how a mixin reaches host data through abstract getters since it has no constructor, and that the host becomes a subtype of every mixin it applies.

for a senior

Show judgement about what belongs in a mixin: small, cohesive cross-cutting behaviour such as logging, not a grab bag that hides dependencies behind abstract getters.

for a principal

Weigh mixins against composition by delegation for cross-cutting API client concerns, considering testability, discoverability and how much hidden coupling a team can absorb.

## What a mixin is in Dart A **mixin** is a reusable set of class members — fields, methods, getters, setters and operators — that you can add to many classes without making them share a superclass. Dart's own docs describe mixins as a way of defining code that can be reused in multiple class hierarchies, providing member implementations en masse. Picture three API clients in one Flutter app: `UserApi`, `OrderApi` and `PaymentApi`. Each already has its own place in a hierarchy, yet all three should log every request in the same format. A shared superclass would force them into one hierarchy; copy-paste would drift. A mixin supplies the logging once and each client opts in. ## Declaring a mixin You declare one with the `mixin` keyword: ```dart mixin Logging { final List<String> history = []; // mixins may hold state String get logTag; // abstract: the host must supply it void log(String message) { history.add(message); print('[$logTag] $message'); } } ``` What a `mixin` declaration may contain: - **instance fields**, including initialised ones like `history` above; - **concrete methods, getters and setters**, which the host inherits; - **abstract members**, which every non-abstract host must implement; - an **`implements` clause**, which obliges the host to satisfy an interface; - an **`on` clause**, which restricts which superclasses it can be applied on (a separate topic). What it may **not** contain: - an `extends` clause — a plain mixin never names a superclass; - a **constructor** of any kind — the analyzer's message is simply "Mixins can't declare constructors" — so it cannot take constructor parameters to initialise its own fields. Because it has no constructor, a mixin cannot be created with `Logging()`. It exists only to be applied. ## Applying a mixin with `with` ```dart class UserApi with Logging { @override final String logTag = 'UserApi'; Future<void> fetchUser(String id) async { log('GET /users/$id'); } } class OrderApi extends BaseApi with Logging, Metrics { @override String get logTag => 'OrderApi'; } ``` Key rules: 1. `with` comes **after** `extends` when both are present; with no `extends`, the superclass is `Object`. 2. You may list **several mixins**, comma-separated; their order matters when two of them define the same member. 3. The class **must implement every abstract member** the mixin declares, unless the class is itself `abstract`. 4. The resulting class is a **subtype of each mixin**: `UserApi() is Logging` is `true`, so a function can accept any `Logging` value. ## Getting data from the host Since a mixin cannot take constructor parameters, the standard way to reach host data is an **abstract getter** (`String get logTag;`). The host satisfies it with a field or a getter. The alternative, an `implements` clause on the mixin, works the same way: it makes the mixin declare that the host provides an interface's members without implementing them itself. ## Mixins in the Dart 3 era Before Dart 3.0, any class with no declared constructors and a superclass of `Object` could be mixed in. Since 3.0, a class in a library at language version 3.0 or later can be mixed in only if it is declared `mixin` or `mixin class`. Code written today should declare mixins with `mixin`. | Feature | `mixin` | `class` | |---|---|---| | Instantiate with a constructor call | No | Yes | | Declare a constructor | No | Yes | | Hold instance fields | Yes | Yes | | Apply with `with` | Yes | No (since Dart 3.0) | | Use as a type (`x is Logging`) | Yes | Yes | ## Where interviewers probe A screening question usually asks for the declaration syntax, the `with` keyword, the no-constructor rule and the difference from `extends`. Good candidates add that mixins can carry state, that host data arrives through abstract members, and that listing order matters when members collide.

  • Can a Dart mixin hold state, and how does that state get initialised?
    Yes. A mixin may declare instance fields, and each object of a class that applies it gets its own copy. Because a mixin cannot declare a constructor, those fields are initialised by their declared initialisers, or declared `late`, or set by the host class after construction. Data the mixin needs from outside usually arrives through an abstract getter the host implements.
  • In Dart, is a class that applies a mixin a subtype of that mixin?
    Yes. `class UserApi with Logging` makes `UserApi` a subtype of `Logging`, so `UserApi() is Logging` is true and a `UserApi` can be passed wherever a `Logging` is expected. That lets you write helpers typed against the mixin rather than against each client.

A mixin is like a plug-in module for a set of different appliances: the same timer board fits a kettle, an oven and a heater, each appliance keeps its own body, and the board asks the appliance for power through a socket it must provide.

saying these in an interview costs you the question

  • A mixin can be instantiated directly like a class.
  • A mixin cannot have fields; it only adds methods.
  • A class can only apply one mixin at a time.
  • A mixin takes constructor parameters to receive host data.
  • Any ordinary Dart 3 class can be listed after with.
open as a page

In Dart, what does a mixin's `on` clause do, and when do you need it rather than an abstract member?

level: middleimportance: must knowfreq 48%

basics

~20 s

An on T clause lets a mixin make super calls resolved against T, and allows applying it only to classes whose superclass is a subtype of T. Use it to wrap an inherited method; an abstract member suffices when you only call the host.

open as a page

In Dart, when should you share behaviour across several API client classes with a mixin rather than `extends` or an extension method?

level: middleimportance: should knowfreq 45%

basics

~20 s

Use a mixin when unrelated clients need the same members, possibly with state or overrides, without sharing a superclass. Use extends for a true single is-a hierarchy, and an extension method for stateless helpers on a type you cannot or should not change.

open as a page

In Dart, when `class UserClient extends BaseClient with Logging, Retry` and both mixins override `send` and call `super.send`, which runs first and why?

level: seniorimportance: should knowfreq 35%

basics

~10 s

Retry.send runs first: Dart applies mixins left to right, each creating a new superclass layer, so the last mixin is nearest the class. Its super.send reaches Logging.send, whose super.send reaches BaseClient.send.

open as a page

In Dart 3, why can you no longer mix in an ordinary class, and when would you declare a `mixin class` instead of a `mixin`?

level: middleimportance: nice to knowfreq 25%

basics

~20 s

Since Dart 3.0, a class in a library at language version 3.0 or later can be applied with with only if declared mixin or mixin class. Use mixin class only when the same type must work both as a superclass and as a mixin.

open as a page