What is an Interface?
An interface defines a contract that a class must adhere to. It specifies a set of methods and properties that the class must implement, but it does not provide any implementation itself. In many languages (like Java), you declare an interface explicitly. In Dart, however, every class implicitly defines an interface containing all its instance members (methods, getters, setters). This means you can use any class as an interface.
The implements Keyword
To make a class adhere to an interface (i.e., to implement the contract of another class), use the implements keyword. The implementing class must provide concrete implementations for all members (methods, getters, setters) of the interface class.
Notice that even though Flyable is a class with empty method bodies, when another class implements it, it must provide its own versions of fly() and the getter altitude. The original implementation (if any) is not inherited – only the signature matters.
Implementing Multiple Interfaces
One of the key benefits of interfaces is that a class can implement multiple interfaces, enabling it to fulfill multiple contracts. This is different from inheritance, where a class can only extend one superclass.
Abstract Classes as Interfaces
You can also use abstract classes to define interfaces. Abstract classes can contain both abstract methods (without implementation) and concrete methods. When another class implements an abstract class, it must implement all members (both abstract and concrete).
Difference Between extends and implements
extendscreates a subclass that inherits the implementation of the superclass. You can override methods but you don't have to implement every method (you get them for free).
implementsmakes the class adhere to an interface – it must provide its own implementation for all members of the implemented class. No code is inherited.
- A class can
extendonly one class, but canimplementsmultiple interfaces.
- A class can
Using @override with Interfaces
When you implement a method from an interface, it's good practice (though optional) to use the @override annotation. This helps the compiler ensure you're actually overriding a member, and it improves code readability.
Interface vs Abstract Class vs Mixin
It's important to understand the differences between these three code reuse mechanisms:
- Interface (via
implements): No implementation inheritance, only contract. Can implement multiple.
- Interface (via
- Abstract class (via
extends): Can have both abstract and concrete methods, fields, constructors. Can only extend one.
- Abstract class (via
- Mixin (via
with): Provides implementation but is not meant to be instantiated; can be mixed into multiple classes.
- Mixin (via
Best Practices
- Use interfaces to define capabilities that can be implemented by unrelated classes.
- Name interfaces according to the ability they represent (e.g.,
Flyable,Comparable,Iterable).
- Name interfaces according to the ability they represent (e.g.,
- Keep interfaces small and focused (Interface Segregation Principle).
- Prefer
abstract classover a concrete class as an interface if you want to provide some base implementation (but be aware it will still require full implementation when used withimplements).
- Prefer
- When a class implements multiple interfaces, ensure there are no conflicting method signatures; if there are, you must provide a single implementation that satisfies all.
Complete Example
Key Takeaways
- In Dart, every class defines an implicit interface.
- Use
implementsto make a class adhere to one or more interfaces.
- Use
- When implementing an interface, you must provide implementations for all members of that interface.
- A class can implement multiple interfaces but extend only one superclass.
- Interfaces are ideal for defining contracts that multiple unrelated classes can fulfill.