Flutter/Dart tips : What is Mixin ? is it really helpful or more like useless ?

asuna24

asuna24

Posted on March 3, 2024

Flutter/Dart tips : What is Mixin ? is it really helpful or more like useless ?

Explanation

For those who already learned about Object Oriented Programming must have heard about "inheritance". Where inheritance defined as "a mechanism that allows a class to inherit properties and behaviors from another class".
Example :

Image description

In the example above, we have 1 Vehicle parent class which had 2 child classes, SUV and Sedan. Each of them have 2 kinds of car and each of them had some shared features (turbo usage, rear camera, and hybrid system).

OOP concept teaches us to achieve these kind of needs we can just create Turbo, Camera, and Hybrid class and implement their attributes and functions. Then each of those classes will be inherited based on class who needs that functionality.

But in Dart, every class is limited only able to inherit to 1 class. For example, Civid which already inherited Sedan class cannot inherit Turbo and Camera class to fulfill their features. Or, we just implement turbo, camera, and hybrid system inside all classes that had those features. But eventually this approach can be so frustating to manage because of there are many code duplications for the same functionality. Here comes the usage of Dart's Mixin.

Mixin enables us to create a way to share reusable code between classes but not to inherit them. So Mixin is not a class, its just a way to implement things. It has no constructor, or even attributes. It consists of reusable method only.

How to create a mixin ?

If we want to use inheritance, we can use extends in the class definition.

class Sedan extends Vehicle {...}
Enter fullscreen mode Exit fullscreen mode

If we want to use mixin, we need to create them by using mixin key without any constructor. Just define the method there. To use mixin, we need to put them on our class definition.

// Create mixin
mixin Turbo {
  void useTurbo() {
    print('I\'m using turbo, speed increased');
  }

  void stopTurbo() {
    print('I\'m stopping the turbo');
  }
}

mixin RearCamera {
  void useRearCamera() {
    print('I\'m using rear camera');
  }

  void turnOffCamera() {
    print('I\'m turning off the camera');
  }
}
Enter fullscreen mode Exit fullscreen mode

After defining our mixin, we need to create the class and use key with after the class definition.

class A with Turbo, RearCamera { ... }
Enter fullscreen mode Exit fullscreen mode

Example

class Vehicle {
  final int numberOfWheels;
  final int maxSpeed;
  final String color;

  Vehicle({
    required this.numberOfWheels,
    required this.maxSpeed,
    required this.color,
  });

  void start() {
    print('I\'m starting');
  }

  void drive() {
    print('I\'m driving');
  }
}

class Sedan extends Vehicle {
  final bool isHatchback;

  Sedan({
    required super.numberOfWheels,
    required super.maxSpeed,
    required super.color,
    required this.isHatchback,
  }) : super();
}

mixin Turbo {
  void useTurbo() {
    print('I\'m using turbo, speed increased');
  }

  void stopTurbo() {
    print('I\'m stopping the turbo');
  }
}

mixin RearCamera {
  void useRearCamera() {
    print('I\'m using rear camera');
  }

  void turnOffCamera() {
    print('I\'m turning off the camera');
  }
}

mixin HybridSystem {
  void useElectricEnergy() {
    print('I\'m using hybrid system');
  }

  void stopElectricEnergy() {
    print('I\'m stopping the hybrid system');
  }
}
Enter fullscreen mode Exit fullscreen mode

Then, we create the grandchild classes here using inheritance and mixing :

class Civid extends Sedan with Turbo, RearCamera {
  Civid({
    required super.numberOfWheels,
    required super.maxSpeed,
    required super.color,
    required super.isHatchback,
  }) : super();
}

class Innovi extends SUV with Turbo, RearCamera, HybridSystem {
  Innovi({
    required super.numberOfWheels,
    required super.maxSpeed,
    required super.color,
    required super.isFourWheelDrive,
  }) : super();
}
Enter fullscreen mode Exit fullscreen mode

By defining classes above, we can see that Civid inherits Sedan but since Civid had Turbo and RearCamera feature, then it uses those mixin. The same applied to Innovi which had Turbo, RearCamera, and HybridSystem. By using this approach, we are reducing code duplication for the exact same functionality.

void main() {
  final Civid cividObject = Civid(
    numberOfWheels: 4,
    maxSpeed: 200,
    color: 'blue',
    isHatchback: true,
  );
  // Civid can use turbo and rear camera only
  cividObject.useTurbo();
  cividObject.useRearCamera();

  final Innovi innoviObject = Innovi(
    numberOfWheels: 2,
    maxSpeed: 200,
    color: 'red',
    isFourWheelDrive: true,
  );
  // Innovi can use turbo, rear camera, and hybrid system
  innoviObject.useTurbo();
  innoviObject.useRearCamera();
  innoviObject.useElectricEnergy();
  innoviObject.stopElectricEnergy();
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

Dart as an Object Oriented Programming language enabled us to use inheritance with only 1 class inherited. What if we need more functionality for our class but we're afraid to create many code duplication for the same usage for a class ? Mixin is the answer. Mixin could be super helpful if we have some reusable code that can be used across classes that need the exact same functionality.

Thank you!

πŸ’– πŸ’ͺ πŸ™… 🚩
asuna24
asuna24

Posted on March 3, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related