Dart Interfaces
Contracts that define what classes must implement
🤝 What are Dart Interfaces?
Interfaces define contracts that classes must follow. In Dart, any class can be used as an interface using the 'implements' keyword, ensuring consistent method signatures across different classes.
// Interface (can be any class)
class Flyable {
void fly() => print('Flying');
}
// Class implementing the interface
class Bird implements Flyable {
void fly() => print('Bird is flying');
}
Interface Concepts
Contract
Defines what methods must exist
abstract class Drawable {
void draw(); // Must be implemented
}
Implementation
Classes must provide method bodies
class Circle implements Drawable {
void draw() => print('Drawing circle');
}
Multiple Interfaces
Classes can implement multiple interfaces
class Duck implements Flyable, Swimmable {
void fly() => print('Duck flying');
void swim() => print('Duck swimming');
}
Polymorphism
Same interface, different implementations
Drawable shape1 = Circle();
Drawable shape2 = Square();
shape1.draw(); // Different behavior
🔹 Basic Interface Implementation
Create and implement a simple interface:
// Interface definition (using abstract class)
abstract class Vehicle {
void start();
void stop();
void getInfo();
}
// Class implementing the Vehicle interface
class Car implements Vehicle {
String brand;
String model;
Car(this.brand, this.model);
@override
void start() {
print('$brand $model engine started');
}
@override
void stop() {
print('$brand $model engine stopped');
}
@override
void getInfo() {
print('Car: $brand $model');
}
}
class Motorcycle implements Vehicle {
String brand;
int engineSize;
Motorcycle(this.brand, this.engineSize);
@override
void start() {
print('$brand motorcycle (${engineSize}cc) started with a roar!');
}
@override
void stop() {
print('$brand motorcycle stopped');
}
@override
void getInfo() {
print('Motorcycle: $brand ${engineSize}cc');
}
}
void main() {
Vehicle car = Car('Toyota', 'Camry');
Vehicle motorcycle = Motorcycle('Harley', 1200);
List vehicles = [car, motorcycle];
for (Vehicle vehicle in vehicles) {
vehicle.getInfo();
vehicle.start();
vehicle.stop();
print('---');
}
}
Output:
Car: Toyota Camry
Toyota Camry engine started
Toyota Camry engine stopped
---
Motorcycle: Harley 1200cc
Harley motorcycle (1200cc) started with a roar!
Harley motorcycle stopped
---
🔹 Multiple Interface Implementation
A class can implement multiple interfaces:
// Multiple interfaces
abstract class Flyable {
void fly();
}
abstract class Swimmable {
void swim();
}
abstract class Walkable {
void walk();
}
// Class implementing multiple interfaces
class Duck implements Flyable, Swimmable, Walkable {
String name;
Duck(this.name);
@override
void fly() {
print('$name is flying through the sky');
}
@override
void swim() {
print('$name is swimming in the water');
}
@override
void walk() {
print('$name is walking on land');
}
}
class Fish implements Swimmable {
String species;
Fish(this.species);
@override
void swim() {
print('$species is swimming underwater');
}
}
class Bird implements Flyable, Walkable {
String type;
Bird(this.type);
@override
void fly() {
print('$type is soaring in the air');
}
@override
void walk() {
print('$type is hopping on the ground');
}
}
void main() {
Duck duck = Duck('Donald');
Fish fish = Fish('Goldfish');
Bird bird = Bird('Eagle');
print('--- Duck abilities ---');
duck.fly();
duck.swim();
duck.walk();
print('\n--- Fish abilities ---');
fish.swim();
print('\n--- Bird abilities ---');
bird.fly();
bird.walk();
// Using polymorphism with interfaces
print('\n--- All swimmers ---');
List swimmers = [duck, fish];
for (Swimmable swimmer in swimmers) {
swimmer.swim();
}
}
Output:
--- Duck abilities ---
Donald is flying through the sky
Donald is swimming in the water
Donald is walking on land
--- Fish abilities ---
Goldfish is swimming underwater
--- Bird abilities ---
Eagle is soaring in the air
Eagle is hopping on the ground
--- All swimmers ---
Donald is swimming in the water
Goldfish is swimming underwater
🔹 Interface vs Inheritance
Understanding when to use interfaces vs inheritance:
Use Interfaces When:
- Multiple inheritance needed: Class needs multiple contracts
- Unrelated classes: Different classes need same behavior
- Contract definition: Define what must be implemented
- Flexibility: Allow different implementations
Use Inheritance When:
- Code reuse: Share common implementation
- IS-A relationship: Child is a type of parent
- Gradual specialization: Add features to base class
// Example combining both inheritance and interfaces
abstract class Printable {
void print();
}
abstract class Saveable {
void save();
}
class Document {
String title;
String content;
Document(this.title, this.content);
void display() {
print('Document: $title');
print('Content: $content');
}
}
// Using both inheritance and interfaces
class PDFDocument extends Document implements Printable, Saveable {
PDFDocument(String title, String content) : super(title, content);
@override
void print() {
print('Printing PDF: $title');
}
@override
void save() {
print('Saving PDF: $title to disk');
}
}
void main() {
PDFDocument pdf = PDFDocument('My Report', 'This is the report content');
// Using inherited method
pdf.display();
// Using interface methods
pdf.print();
pdf.save();
}
Output:
Document: My Report
Content: This is the report content
Printing PDF: My Report
Saving PDF: My Report to disk