Dart Interface
In Dart, an interface defines a contract that classes can implement. Interfaces specify a set of methods and properties that a class must implement if it wants to adhere to that interface. Dart does not have a separate interface keyword like some other languages; instead, classes implicitly act as interfaces when other classes implement them. Let’s explore interfaces in Dart with examples:
Example of Interface-Like Behavior in Dart
In Dart, any class can act as an interface. When another class implements this “interface,” it must provide implementations for all the methods declared in the interface.
// Define an "interface" class with method signatures class Vehicle { void start(); void stop(); } // Implementing class Car adheres to the Vehicle interface class Car implements Vehicle { @override void start() { print('Car started'); } @override void stop() { print('Car stopped'); } // Additional methods specific to Car class void displayInfo() { print('This is a car'); } } void main() { var car = Car(); car.start(); // Output: Car started car.stop(); // Output: Car stopped car.displayInfo(); // Output: This is a car }
Using Interfaces for Polymorphism
One of the primary benefits of interfaces is polymorphism, where different classes can be treated interchangeably if they adhere to the same interface:
// Another class adhering to Vehicle interface class Motorcycle implements Vehicle { @override void start() { print('Motorcycle started'); } @override void stop() { print('Motorcycle stopped'); } // Additional methods specific to Motorcycle class void displayInfo() { print('This is a motorcycle'); } } void main() { // List of vehicles treated uniformly by Vehicle interface var vehicles = [Car(), Motorcycle()]; for (var vehicle in vehicles) { vehicle.start(); // Polymorphic call vehicle.stop(); // Polymorphic call // vehicle.displayInfo(); // Error: This method is not defined for the Vehicle interface } }
Abstract Classes as Interfaces
Dart also supports abstract classes, which can define methods without providing implementations. These abstract classes can be used similarly to interfaces by implementing their methods in subclasses:
// Abstract class defining methods without implementation abstract class Animal { void makeSound(); } // Implementing classes providing actual method implementations class Dog extends Animal { @override void makeSound() { print('Bark'); } } class Cat extends Animal { @override void makeSound() { print('Meow'); } } void main() { var animals = [Dog(), Cat()]; for (var animal in animals) { animal.makeSound(); // Output: Bark, Meow } }
Difference between Interface and Abstract Class
Abstract Class
An abstract class is a class that cannot be instantiated directly. It contains some abstract methods (methods without implementation) that must be implemented by a subclass. Abstract classes are useful when we want to share some common functionality but leave the details for the subclasses to define.
Example – Abstract Class:
abstract class Animal { void sound(); // Abstract method, must be implemented by subclasses void breathe() { print("Breathing..."); } } class Dog extends Animal { @override void sound() { print("Bark"); } } void main() { var dog = Dog(); dog.sound(); // Output: Bark dog.breathe(); // Output: Breathing... }
Interface
In Dart, all classes can act as interfaces. When a class is used as an interface, it only provides the contract (method signatures) and must be fully implemented by any class that uses it. Interfaces do not provide any implementation, just the method declarations.
Example – Interface:
class Animal { void sound(); // Method declaration without implementation } class Dog implements Animal { @override void sound() { print("Bark"); } } void main() { var dog = Dog(); dog.sound(); // Output: Bark }
When to Use What
- Abstract Class:
- Use an abstract class when you have common functionality that multiple subclasses will share, but you need to enforce that certain methods be implemented by the subclasses. Abstract classes can have both implemented methods and abstract methods.
- Use when you want to define some base functionality and leave the implementation to subclasses.
- Interface:
- Use an interface when you want to define a contract that any class can implement. Interfaces only define the method signatures and do not provide any implementation.
- Useful when you want multiple classes to adhere to a specific behavior but don’t need to share implementation details.