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 :
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 {...}
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');
}
}
After defining our mixin, we need to create the class and use key with
after the class definition.
class A with Turbo, RearCamera { ... }
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');
}
}
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();
}
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();
}
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!
Top comments (0)