Mixins in Dart (Flutter) — And How it is different from Inheritance ?

Syed Ibrahim
Flutter Community
Published in
6 min readMar 8, 2024

--

Hello all!

Let’s talk about mixins today, with a question.

What is mixin? and how it is different from inheritance. If you know how it is different from inheritance then scroll to section 2 and check how to implement mixins :) if not we’ll break it down right here!

Section 1 : Let’s start with definition

mixin is a way to reuse code by allowing classes to inherit behaviours and properties from multiple sources.

Right ? this is what you’ll find mostly when you search about mixins. And most probably you’ll get confused it with inheritance like me :) . So, before we start with mixins it is very important to know about is-a relationship (inheritance) and has-a relationship (composition) .

So let us have some quick clarification on these concepts. have a look at this image

What you observe?

From the real-time example attached for reference. You can observe here that-

  • Samsung is-a Mobile
  • Samsung has-a Camera and has-a Bluetooth.

Now check out the following definitions to get more insight.

is-a Relationship : It can be defined as direct relationship between two class where one class (lets say Class B) is subclass of other class (lets say Class A). Which is called as INHERITANCE.

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

has-a Relationship: It can be defined as an association between two classes where one class (let’s say Class A) contains an instance of another class (let’s say Class B) as one of its members. This association allows Class A to have access to the functionalities and properties of Class B, thus known as COMPOSITION.

Finally let’s see how it looks programmatically.

*Attention: focus on comments*

//parent class
class Mobile {
}



//subclass or child class
//example of is-a relationship as Samsung extends Mobile
class Samsung extends Mobile {

//example of has-a relationship
Wifi wifi = Wifi();
Camera camera = Camera();

}

I Hope you’re now clear about is-a and has-a relationship.

Now let’s read the definition of mixin again, which I hope you already did.

mixin is a way to reuse code by allowing classes to inherit behaviours and properties from multiple sources, “without establishing a strict hierarchy of parent child relationship which is what inheritance (is-a relationship) does”.

So classes using mixin can inherit all properties and functions but cannot be termed as subclass.

why????

Because mixins establish a relationship similar to, but not exactly, a “has-a” relationship between a class and the functionalities provided by the mixin. It gains access to the methods and properties defined in the mixin.

However, the difference is the class itself doesn’t hold an instance of the mixin; rather, it just inherits it. There’s no strict hierarchy involved. So as it is not being bound by a strict hierarchy of parent-child relationships.

This flexibility allows classes to benefit from the functionalities provided by mixins without forming a direct “is-a relationship” with them.

Understood? If not, hang tight — we’ll dive into it in Section 2 and you’ll get it in no time!

Section 2 : Implementation of mixin

let’s dive now into how we can implement them in Dart and Flutter.

1.Declaring a Mixin : We declare a mixin using the mixin keyword followed by the mixin's name. Mixins can contain methods and properties.

mixin MixinLogger {

void logMessage(String message) {
print("MESSAGE: $message");
}

}

2.Using Mixins : To use a mixin in a class, we use the with keyword followed by the mixin's name. This allows the class to inherit the functionalities defined in the mixin.

class APIService with MixinLogger { 

void getPosts() {
try {
final response = http.get('https://www.example.com/posts');
} catch (Exception e) {
// Call mixin method
logMessage(e.toString());
}
}

}

Now!

void main(){
APIService apiService = APIService();

if(apiService is MixinLogger){
print("APIService is of type MixinLogger");
}
else{
print("APIService is not of type MixinLogger");
}
}

What will be the output?

If you don’t know and skipped section 1 , please have a look on it then.

So, The output will be APIService is not off type MixinLogger”.

why???? again same answer but this time i hope you will understand.

Because mixins establish a relationship similar to, but not exactly, a “has-a” relationship between a class and the functionalities provided by the mixin. It gains access to the methods and properties defined in the mixin.

However, the difference is the class itself doesn’t hold an instance of the mixin; rather, it just inherits it. There’s no strict hierarchy involved. So as it is not being bound by a strict hierarchy of parent-child relationships.

This flexibility allows classes to benefit from the functionalities provided by mixins without forming a direct “is-a relationship” with them.

Now let’s explore more features.

3. Features in mixin:

on keyword in mixin:

If you want to restrict your mixin to be used by only those classes which needs to subclass of your desired class then we should declare mixin class with on keyword.

mixin <mixinname> on <class_name_on_which_mixin_should_restricted>

*Attention: focus on comments*


mixin MixinDiscount on Product{

performDiscountOperation(double price,double discount){
//perform discount operations
}

}


class Product{

}

Here Discount mixin will be constrained and can only be used with class which is a subclass of product class Type.

//It will throw compile time error that
//Telvision can't be mixed as it should be implement Product
class Television with MixinDiscount{

}
//it will work as it adheres the rules
class Television extends Product with MixinDiscount{

void doSomeOperation(){
//you can call methods directly now
performDiscountOperation(1000,10);
}

}

inheriting multiple mixins :

Let’s declare two mixins MixinA and MixinB with one functions each.


mixin MixinA{

void functionA(){
print("function A");
}

}

mixin MixinB{

void functionB(){
print("function B");
}

}
class Consumer with MixinA,MixinB{

}

void main(){
final consumer = Consumer();
//Now consumer can be able to use both functions from mixin A and B
consumer.functionA();
consumer.functionB();
}

What if multiple mixins having same function signatures?

Dart got you covered :)

mixin MixinA {
void foo() {
print('A.foo');
}
}

mixin MixinB {
void foo() {
print('B.foo');
}
}

Now, let’s define a class C that uses both mixins A and B:

class ClassC with MixinA, MixinB {
// Class implementation...
}


void main(){
final c = ClassC();
c.foo(); // Output: B.foo
}

In this situation, the classC gets the foo() method from both mixins A and B But Dart has to decide which one to use since there’s a conflict. It picks the foo() method from the last mixin used, which is B. So, when we make an instance of the class C and call foo(), it calls the func from mixin B.

The programming languages that support multiple inheritance have complexity for this type of scenario, which is known as the diamond problem. But for Dart Easy, right? :)

That’s all for now.

Thanks for reading !!!

My First Ever Blog ! I Hope It Helped :)

Ibrahim Syed.

--

--