Mixins vs Interfaces in Dart

yousaf@345
3 min readMay 18, 2024

In Dart, both mixins and interfaces are powerful features that help achieve code reuse and flexibility. They allow you to implement shared functionality in a modular and manageable way. While they serve similar purposes, there are distinct differences in how and when to use them. This article will explore these differences, providing a detailed explanation and five examples to illustrate their usage.

Mixins

Mixins are a way of reusing a class’s code in multiple class hierarchies. They allow you to add functionality to a class without using inheritance. Mixins are useful when you want to share behavior between different classes without implying an “is-a” relationship.

mixin MixinName {
//properties and Methods
}

Example 1: Basic Mixin

mixin Swimmer {
void swim() {
print('Swimming…');
}
}
class Fish with Swimmer {}
void main() {
Fish fish = Fish();
fish.swim(); // Output: Swimming…
}

Explanation:
1. mixin Swimmer declares a mixin.
2. The swim method is defined inside the mixin.
3. class Fish with Swimmer applies the Swimmer mixin to the Fish class.
4. The Fish class can now use the swim method.

Example 2: Mixin with State

mixin Walker {
int steps = 0;
void walk() {
steps += 1;
print('Walking… Steps: $steps');
}
}
class Human with Walker {}
void main() {
Human human = Human();
human.walk(); // Output: Walking… Steps: 1
human.walk(); // Output: Walking… Steps: 2
}

Explanation:
1. steps is a property in the Walker mixin.
2. The walk method modifies the steps property.
3. The Human class uses the Walker mixin, gaining its properties and methods.

Interfaces

Interfaces in Dart are used to define a contract that a class must follow. Unlike mixins, interfaces do not provide any implementation; they only define methods and properties that must be implemented by the class.

Syntax

abstract class InterfaceName {
// Methods and properties
}

Example 3: Basic Interface

abstract class Driver {
void drive();
}
class Car implements Driver {
@override
void drive() {
print('Driving a car…');
}
}
void main() {
Car car = Car();
car.drive(); // Output: Driving a car…
}

Explanation:
1. abstract class Driver defines an interface with the drive method.
2. The Car class implements the Driver interface and provides the drive method implementation.

Example 4: Interface with Properties

abstract class Device {
String get name;
void turnOn();
void turnOff();
}
class Computer implements Device {
@override
String get name => 'Computer';
@override
void turnOn() {
print('$name is now ON');
}
@override
void turnOff() {
print('$name is now OFF');
}
}
void main() {
Computer computer = Computer();
computer.turnOn(); // Output: Computer is now ON
computer.turnOff(); // Output: Computer is now OFF
}

Example 5: Combining Mixins and Interfaces

abstract class Animal {
void eat();
}
mixin Flyer {
void fly() {
print('Flying…');
}
}
class Bird implements Animal with Flyer {
@override
void eat() {
print('Eating…');
}
}
void main() {
Bird bird = Bird();
bird.eat(); // Output: Eating…
bird.fly(); // Output: Flying…
}

1. abstract class Animal defines an interface with the eat method.
2. mixin Flyer defines a mixin with the fly method.
3. The Bird class implements the Animal interface and applies the Flyer mixin, providing the implementation for the eat method and inheriting the fly method.

Mixins and interfaces are essential tools in Dart for creating flexible and reusable code. Mixins allow you to share behavior across multiple classes without inheritance, while interfaces define contracts that classes must follow.

I hope you have learned a lor of new things 😊

Thanks for reading 📚

--

--