Interfaces in Dart
In Dart, interfaces define a contract that classes must follow. Think of an interface as a blueprint that specifies what methods and properties a class should have, without providing the actual implementation. It's like having a job description that lists all the responsibilities, but doesn't tell you exactly how to do each task.
Understanding Interfaces
Unlike some other programming languages, Dart doesn't have a separate interface keyword. Instead, every class in Dart implicitly defines an interface. This means you can use any class as an interface by implementing it in another class.
Implementing Interfaces
To implement an interface in Dart, you use the implements keyword. When a class implements an interface, it must provide concrete implementations for all the methods and properties defined in that interface.
// Define a class that will serve as an interface
class Animal {
void makeSound() {
print("Some generic animal sound");
}
void move() {
print("Animal is moving");
}
}
// Implement the Animal interface
class Dog implements Animal {
@override
void makeSound() {
print("Woof! Woof!");
}
@override
void move() {
print("Dog is running");
}
}
class Cat implements Animal {
@override
void makeSound() {
print("Meow!");
}
@override
void move() {
print("Cat is sneaking");
}
}
Multiple Interface Implementation
One of the powerful features of interfaces is that a class can implement multiple interfaces. This allows for flexible design patterns and code reusability.
class Flyable {
void fly() {
print("Flying high!");
}
}
class Swimmable {
void swim() {
print("Swimming gracefully!");
}
}
// A class can implement multiple interfaces
class Duck implements Animal, Flyable, Swimmable {
@override
void makeSound() {
print("Quack! Quack!");
}
@override
void move() {
print("Duck is waddling");
}
@override
void fly() {
print("Duck is flying over the pond");
}
@override
void swim() {
print("Duck is swimming in the water");
}
}
Abstract Classes as Interfaces
You can also create abstract classes to serve as more formal interfaces. Abstract classes can contain both abstract methods (without implementation) and concrete methods (with implementation).
abstract class Vehicle {
// Abstract method - must be implemented
void startEngine();
// Concrete method - can be inherited or overridden
void honk() {
print("Beep beep!");
}
}
class Car implements Vehicle {
@override
void startEngine() {
print("Car engine started with a key");
}
@override
void honk() {
print("Car horn: HONK HONK!");
}
}
class Motorcycle implements Vehicle {
@override
void startEngine() {
print("Motorcycle engine started with a button");
}
// Using the inherited honk method
}
Key Benefits of Interfaces
| Benefit | Description |
|---|---|
| Flexibility | Classes can implement multiple interfaces |
| Consistency | Ensures all implementing classes have required methods |
| Polymorphism | Different classes can be treated uniformly |
| Testing | Easy to create mock implementations for testing |
Interface vs Inheritance
It's important to understand the difference between implementing an interface and extending a class:
- Implements: You must provide your own implementation for all methods
- Extends: You inherit the parent's implementation and can optionally override methods
// Using implements - must provide all implementations
class Robot implements Animal {
@override
void makeSound() {
print("Beep boop!");
}
@override
void move() {
print("Robot is walking mechanically");
}
}
// Using extends - inherits parent's implementation
class Puppy extends Dog {
@override
void makeSound() {
print("Yip yip!"); // Override parent's implementation
}
// move() method is inherited from Dog
}
Interfaces in Dart provide a powerful way to define contracts and create flexible, maintainable code. They're especially useful when you want to ensure that different classes follow the same structure while allowing for different implementations.