Today, we’ll find out what the heck a mixin is and how it solves the Deadly Diamond of Death.
Inheritance
A regular class can inherit properties from a different class. You do this in Dart and TypeScript by using the extends
keyword.
class MyApp extends StatelessWidget { // ...}
By extending (or inheriting) a class, you gain access to all the properties and methods of the parent class. You can use those properties and methods, add new ones to the subclass, or override the functionality of the parent methods.
class MyApp extends StatelessWidget {
@override Widget build(BuildContext context) { // ... }}
Inheritance is a very strict relationship, where the subclass is of the parent class type.
In our example, the MyApp
class is of type StatelessWidget
. You can only inherit from one parent class.
class MyApp extends StatelessWidget {
@override Widget build(BuildContext context) { // ... }}
Mixins
Mixins are similar, but less strict. Mixins use the with
keyword. While a class is “inherited,” a mixin is “included.”
class MyApp extends StatelessWidget with ConnectivityMixin {
@override Widget build(BuildContext context) { // ... }}
Mixins do not have a paired relationship. You can think of them as nice helper functions that you can bring into your class. And you are not limited to including just one mixin in your class.
For example, you might have a connectivity mixin that checks to see if the user is connected to the internet and a logging mixin that prints logs.
You can include both of these mixins and have access to their functions within a single class.
class MyApp extends StatelessWidget with ConnectivityMixin with LoggingMixin {
@override Widget build(BuildContext context) { // ... }}
Deadly Diamond of Death
Mixins also solve what is called the “Deadly Diamond of Death”. The name is a bit dramatic, but it refers to the problem that arises if a class inherits from two classes, and those classes inherit from the same base class. If one or both override a function, which one do you use?
In Dart, you can only inherit from one class. This automatically makes it impossible to create a Deadly Diamond of Death. However, you can still create these diamonds using mixins, but with mixins, the problem of which function to use is solved.
First, mixins don’t create new instances like inheritance does. Instead, the methods are simply injected into the subclass.
mixin A { void greet() { print("Hello from A"); }}
class B with A {} // No new instance of A, just reusing the mixinclass C with A {} // Again, reuses the mixinclass D with B, C {} // Still no duplicate instances of A
void main() { D obj = D(); obj.greet(); // Output: Hello from A}
You can still override functions when using a mixin. But Dart uses a “last mixin wins” approach, so there is no ambiguity. Whichever mixin is the last one included, that mixin’s logic will be used.
mixin A { void greet() => print("Hello from A");}
mixin B { void greet() => print("Hello from B");}
class C with A, B {} // B is applied last, so it overrides A
void main() { C obj = C(); obj.greet(); // Output: Hello from B}

Want to learn Flutter?
We teach you all you need to confidently build apps at hungrimind.com/learn/flutter
Thank you for reading!
YouTube Video
Get articles right in your inbox
No spam, unsubscribe anytime. We treat your inbox with respect.