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).
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.
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
onkeyword to restrict the types that can use it (see below).
- A mixin cannot extend any class, though it can use the
- Prior to Dart 2.12, mixins could only be created from classes with no constructors and no
supercalls. Now, with themixinkeyword, these restrictions are explicit.
- Prior to Dart 2.12, mixins could only be created from classes with no constructors and no
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.
Mixins vs Inheritance vs Interfaces
- Inheritance (
extends): Creates an 'is‑a' relationship, and you get implementation. A class can extend only one superclass.
- Inheritance (
- Interfaces (
implements): Enforces a contract but gives no implementation. A class can implement multiple interfaces.
- Interfaces (
- Mixins (
with): Gives you implementation without the 'is‑a' relationship. A class can use multiple mixins.
- 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.
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.
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
onkeyword to document and enforce the required superclass type.
- Use the
- Be mindful of method name conflicts; order mixins deliberately.
Complete Example
Key Takeaways
- Mixins (defined with
mixin) allow you to reuse code across unrelated classes.
- Mixins (defined with
- Use the
withkeyword to apply one or more mixins to a class.
- Use the
- Mixins cannot have constructors and can use
onto restrict usage to subtypes of a given class.
- Mixins cannot have constructors and can use
- Method conflicts are resolved by the order of mixins (last wins).
- Mixins provide a flexible alternative to multiple inheritance.