paint-brush
Dart: What Are Mixins and What Can I Use Them For?by@shubhamhackz
782 reads
782 reads

Dart: What Are Mixins and What Can I Use Them For?

by Shubham SoniJanuary 5th, 2021
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

From my time with Dart, one topic which I feel is a little tricky is mixins. For Java developers, it is a completely new concept to learn.

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - Dart: What Are Mixins and What Can I Use Them For?
Shubham Soni HackerNoon profile picture

I’m an app developer who loves to makes awesome mobile applications. Recently Flutter has received a lot of exposure, attracting many developers from Android, IOS and even from the web.

After the release of Flutter 1.0, it piqued the curiosity of almost every mobile developer. When I first looked at it, it seemed very interesting so I decided to give it a shot.

When I realized that I'd have to learn a new programming language to start diving deep in Flutter, I almost planned to skip trying it. Learning a new programming language is always a time-consuming process. That said, when I looked at some of the examples on Dart’s website, everything changed. Dart feels like home. It is a very clean and easy to understand language, especially if you have a programming background in languages such as Java, JavaScript, C# or any other object-orientated programming language. You will be up and running Dart programs in a matter of hours.

From my time with Dart, one topic which I feel is a little tricky is mixins. For Java developers, it is a completely new concept to learn as Java does not support multiple inheritance or mixins. Java tries to make up for this by using Interfaces, but that is not as useful or flexible as mixins.

So, let's first try to understand what is mixins?

💫 What mixin really is?

I think the most concise definition of mixin is provided by Wikipedia:

“In object-oriented programming languages, a Mixin is a class that contains methods for use by other classes without having to be the parent class of those other classes.”

In other words, mixins are normal classes from which we can borrow methods (or variables) from without extending the class. In Dart, we can do this by using the keyword with. If you want to use class B as a mixin for class A then:

class B {  //B is not allowed to extend any other class other than object
  method(){
     ....
  }
}

class A with B {
  ....
     ......
}
void main() {
  A a = A();
  a.method();  //we got the method without inheriting B
}

The code class A with B is equivalent to class A extends Object with B. Right now, classes can only be used as mixins once they only extend object. Classes which extend other classes cannot be used as a mixin. This could change in the future however since Dart is continuously evolving and there is already an experimental feature which allows us to use mixins, which extends class other than Object. Maybe at the time of reading this article, there could be some minor changes how mixins behave. So always keep an eye on mixin specifications.

Although we can’t use mixin class that extends classes other than Object, we can extend or implement the base class (Class A in this example) which is using mixin class:

class B {  //B is not allowed to extend any other class other than object
  method(){
     ....
  }
}

class C {
  ...
    ...
}

class A extends C with B { . //we can extends of implement class A
  ....
     ......
}
void main() {
  A a = A();
  assert(a is B);  // a is b = true
  assert(a is C);  // a is c = true
  a.method();  //we got the method without inheriting B
}

Mixins enables a programming language to mimic an benefit from features such as multiple inheritance and code reuse while also reducing the risk of running into problems such as the Deadly Diamond of Death (DDD).

Some people describe mixins as an interface with implementations.

😨 What is deadly diamond of death(DDD) in multiple inheritance?

Suppose we have an abstract class called Performer.

abstract class Performer {
   void perform();
}

Now we will make two concrete classes Dancer and Singer which extends Performer.

class Dancer extends Performer {
   void perform() {
      print('Dance Dance Dance ');
   }
}
class Singer extends Performer {
   void perform() {
      print('lalaaa..laaalaaa....laaaaa');
   }
}

Extending Performer is the only way I can dance and sing.

Now suppose dart supports multiple inheritance and a class called Musician extends both the classes Dancer and Singer.

Note: Dart only supports Single inheritance, I’m just assuming here, what will happen if dart supported Multiple Inheritance like C++:
class Musician extends Dancer,Singer {
   void showTime() {
      perform();  
   }
}

Can you guess which perform() method would be called in Musician class?

Confused? This is what a compiler feels when we try to run this code. Because there’s no actual way for us to decide which is the right method to call. This very situation is known as the deadly diamond of death and it is a core problem of multiple inheritance. Thankfully, we can fix this using mixins.

😍 What mixin can do for us?

As the official docs states:

“To implement a mixin, create a class that extends Object and declares no constructors. Unless you want your mixin to be usable as a regular class, use the mixin keyword instead of class.”

The mixin keyword was introduced in Dart 2.1 and it is analogous to abstract class in some ways and different from it in other ways. Like abstract class, you can declare abstract methods in mixins and it cannot be instantiated. But unlike abstract, you can’t extend a mixin.

You can either use the keyword mixin, abstract class, or a normal class as a mixin. Let’s take a look at how we can solve the above problem with mixins.

Always keep in mind that mixin is not multiple inheritance, instead, they are just a way to reuse our code from a class in multiple hierarchies without needing to extend them. It's like being able to use other people assets without being their children. It's cool hah! 😝

First, we have to create our Performer class with a method 

perform()
 ,

class Performer {
   void perform() {
     print('performing...');
   }
}

Next, we create the class Dancer which contains a method named

perform()

mixin Dancer {
   void perform() {
     print('Dance...Dance...Dance..');
   }
}

Now we will declare another class called Singer which will contain the same method 

perform()

mixin Singer {
   void perform() {
     print('lalaaa..laaalaaa....laaaaa');
   }
}

Let's create one more class Musician which will use both of these classes along with Performer class:

class Musician extends Performer with Dancer,Singer {
   void showTime() {
     perform();
   }
}
Now if we try to run the above code, we will get the output lalaaa..laaalaaa....laaaa , can you guess why?

When mixing classes, the classes used as mixins are not parallel but instead on top of the class using it. This is the reason why methods do not conflict with one another, allowing us to use codes from multiple classes without having to deal with the vulnerabilities of multiple inheritance.

If you are confused by this, don’t panic, I will explain how mixins are evaluated.

For determining which class method will be executed when using mixins, follow these simple steps:

If the class using mixins is extending any class then put that class on top of the stack. i.e class Musician extends Performer

Always remember the order in which you declare mixins, this is very important because it decides which class is more important. If mixins contain identical methods, then the mixin class that is declared later will be executed (Declaring a mixin after another raises its “Importance”).

In our example, we declared Dancer before the Singer, so it is more “Important” and therefore would go below Performer. I.e class Musician extends Performer with Dancer.

After Dancer we declared Singer, so put the Singer below Dancer in the stack:

Finally, add the class which is using mixins i.e Musician into the stack. This class would be the most important or most specific class. If this class contains any identical methods to mixins or super class, then the methods in this class would be called first… always.

Got it? The idea behind how mixins can be used as a way to reuse code without having to deal with multiple inheritance and the problems which arise because of it.

Now we will try to focus on some other advanced things that we can do with mixins.

😯 Doing some more stuff with mixin!

Although we can do a lot of normal and advanced things using Dart’s mixins, there is one more thing we need to look at and that is the keyword "on". The keyword "on" is used to restrict our mixin’s use to only classes that either extends or implements the class it is declared on. In order to use the "on" keyword, you must declare your mixin using the mixin keyword.

Below is an example of using the

on
keyword:

class A {}

class B{}

mixin X on A{}

mixin Y on B {} 

class P extends A with X {} //satisfies condition as it extends A
class Q extends B with Y {}
In the above code we are restricting mixins X and Y to be only used by the classes which either implements or extends A and B respectively.

☀️ Conclusion :

The roots of mixins can be found in Lisp Community and its very first uses to smalltalk. Dart is influenced by smalltalk in many ways; it takes many inspirations from it including mixin. Mixins are great for reusing your code without any restrictions in multiple class hierarchies. I believe that there are lots of things which could be done using mixins. I would love to see what you all create with this. Good Luck! Happy Fluttering!

If you enjoyed this story, you can support me by 👏 this. You can also follow me on Twitter , Facebook or Instagram.

Also published at https://medium.com/flutter-community/https-medium-com-shubhamhackzz-dart-for-flutter-mixins-in-dart-f8bb10a3d341