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

🧠 Test Your Knowledge

Which keyword is used to implement an interface in Dart?