Interface-based Polymorphism
Interface-based Polymorphism
About
- Implicit Interfaces: All classes define interfaces
- Multiple Inheritance: Implement many interfaces
- Loose Coupling: Code to interfaces not implementations
- Dart’s Approach: No separate interface keyword
Main Topics
-
Basic Implementation
- Definition:
implements
keyword - Example:
class MockHttpClient implements HttpClient { // Must implement all members }
- Definition:
-
Multiple Interfaces
- Definition: Comma-separated list
- Example:
class Student implements Person, Learner { // Implement both interfaces }
-
Abstract Classes as Interfaces
-
Definition: Partial implementations
-
Example:
abstract class Repository { void save(); } class UserRepo implements Repository { @override void save() {/*...*/} }
-
-
Interface Contracts
- Definition: Required member signatures
- Example:
class Cash implements PaymentMethod { @override void pay(double amount) { // Must implement } }
-
Mixins vs Interfaces
- Definition: Different reuse mechanisms
- Example:
// Interface defines contract // Mixin provides implementation
How to Use
- Testing: Mock implementations
- Plugins: Multiple backends
- API Design: Stable interfaces
- Evolution: Easier refactoring
How It Works
- Type System: Interface is type
- Verification: Compiler checks
- Flexibility: Runtime substitution
- Documentation: Implicit contracts
Example:
abstract class DataStore {
Future<void> save(String key, String value);
}
class MemoryStore implements DataStore {
final _storage = <String, String>{};
@override
Future<void> save(String key, String value) async {
_storage[key] = value;
}
}
class FileStore implements DataStore {
@override
Future<void> save(String key, String value) async {
// File system implementation
}
}
Conclusion
Interface-based polymorphism in Dart enables flexible, testable designs through abstract type contracts. By programming to interfaces rather than concrete implementations, Dart code becomes more modular and adaptable to change.