Mixins in Dart

Mixins is really interesting topic and especially for those coming from Java background. Let’s explore this!

We will see following points:

  1. Why do we need Mixins?
  2. What is it and How can we implement it?
  3. Where does it belong in class hierarchy?
  4. How to strict the usage of Mixins?

Why do we need Mixins?

Let’s say, we have three different types of cars like Gasoline car, Electric car and Hybrid car. Hybrid car must have some functionalities which are same as Gasoline car and Electric car. Something like this:

    class ElectricCar {  
        void startMotor() => print("Start motor");
        bool batteryAvailable() {
            int batteryChargingPercentage = 100;
            // check battery capacity
            return batteryChargingPercentage > 15;
        }
    }

    class GasolineCar {
        void startEngine() => print("Start engine");
    }


    class HybridCar extends ElectricCar, GasolineCar {
        void startCar() {
        batteryAvailable() ? startMotor() : startEngine();
        }
    }

But unfortunately, above code doesn’t run because Dart doesn’t support multiple inheritance. Why? See the the problem Deadly Diamond of Death.

So, Hybrid car can’t extend both Gasoline car and Electric car. It has to provide its own implementation of startEngine and startMotor. Then, there will be same method with same implementation in two different classes. That’s the last thing we want duplicate code. One of the low of programming: Don’t Repeat Yourself (DRY).

How can we solve this? There are two ways to solve:

What is it and How can we implement it?

Mixins provide a way to write reusable code in multiple class hierarchies. Let’s see how can we solve above problem with Mixins:


    mixin ElectricCar {  
        void startMotor() => print("Start motor");
        bool batteryAvailable() {
            int batteryChargingPercentage = 100;
            // check battery capacity
            return batteryChargingPercentage > 15;
        }
    }

    mixin GasolineCar {
        void startEngine() => print("Start engine");
    }

    class HybridCar with ElectricCar, GasolineCar {
        void startCar() {
        batteryAvailable() ? startMotor() : startEngine();
        }
    }

Here, we just changed class declaration of ElectricCar & GasolineCar to mixin declaration and HybridCar with ElectricCar, GasolineCar instead of extends. Now, our HybridClass is up and running! That’s our beautiful Mixin. Following points need to be noted:

  1. If you want to use your mixin as a class then you can declare mixin with class keyword instead of mixin. It works fine!
  2. Mixins can’t have constructors.
  3. If you declare mixin as mixin but not as a class then they can’t be instantiated.

So, we saw using Mixins, how can avoid code duplication.

Where does it belong in class hierarchy and What is type of it?

Tell me, what would be the output of the following code snippet:


    class Phone {
        void dialNumber() => print("Dialing through rotary dial");
    }
        
    mixin KeypadPhone on Phone {
        void dialNumber() => print("Dialing through keypad");
    }
        
    mixin TouchScreenPhone on Phone {
        void dialNumber() => print("Dialing through touch screen");
    }
        
    class TouchAndTypePhone extends Phone with TouchScreenPhone, KeypadPhone {
        void callFlutterTeam() {
            super.dialNumber();
        }
    }
        
    main() {
        final phone = TouchAndTypePhone();
        phone.callFlutterTeam();
    }
     

Output:

    Dialing through keypad

If you have guessed the above output then you are right. But, how? Let’s see the hierarchy of above snippet:

KeypadPhone is immediate parent of TouchAndTypePhone. That’s why it prints Dialing through keypad.
While declaring a class with Mixins order matters. Let’s see how order of TouchScreenPhone & KeypadPhone matters:


    [Type 1]
    class TouchAndTypePhone extends Phone with TouchScreenPhone, KeypadPhone {
    
        void callFlutterTeam() {
            super.dialNumber(); // This will print "Dialing through keypad"
        }
    }

    [Type 2]
    class TouchAndTypePhone extends Phone with KeypadPhone, TouchScreenPhone {
    
        void callFlutterTeam() {
            super.dialNumber(); // This will print "Dialing through touch screen"
        }
    }

How to strict the usage of Mixins?

There are sometimes that you want to usage of Mixins can be allowed to specific hierarchy. Means only allowed class type can use Mixins. If you have seen the above example carefully then we have two Mixins as following:


    mixin KeypadPhone on Phone {
        void dialNumber() => print("Dialing through keypad");
    }

    mixin TouchScreenPhone on Phone {
        void dialNumber() => print("Dialing through touch screen");
    }
      

Here, we used on keyword to restrict KeypadPhone and TouchScreenPhone to only Phone hierarchy. So, classes which are type of Phone class only can use these Mixins.

In conclusion, use Mixin when a particular class is part of multiple class hierarchies. So, it helps you to avoid putting the same code in different class hierarchies.

Thanks folks for reading! Have a amazing day.

Let’s connect on Twitter, Reddit, and Github.

Thanks for reading! Please share this article with others to spread knowledge.

1 thought on “Mixins in Dart”

Leave a Reply

Your email address will not be published. Required fields are marked *