# Interfaces Implícitas en Dart
A diferencia de Java o C#, Dart no tiene una palabra clave `interface`. En su lugar, **cada clase define implícitamente una interfaz** que contiene todos sus miembros públicos.
## ¿Cómo funcionan?
Cualquier clase puede actuar como una interfaz si la implementas usando la palabra clave `implements`.
```dart
// Una clase normal
class Person {
final String name;
Person(this.name);
void greet() {
print('Hello, I am $name');
}
}
// Implementando la interfaz implícita de Person
class Impostor implements Person {
// ⚠️ Debemos implementar TODOS los miembros públicos
@override
String get name => 'Unknown';
@override
void greet() {
print('I am not who you think I am');
}
}
```
## Clases Abstractas como Interfaces
Es común definir clases abstractas puras (sin implementación) para usarlas explícitamente como interfaces.
```dart
// Definición de Interfaz (convención: usar clase abstracta)
abstract class Flyable {
void fly();
double get altitude;
}
abstract class Swimmable {
void swim();
}
// Implementación Múltiple
class Duck implements Flyable, Swimmable {
@override
double altitude = 0;
@override
void fly() {
print('Duck flying');
altitude += 10;
}
@override
void swim() {
print('Duck swimming');
}
}
```
## `extends` vs `implements`
### `extends` (Herencia)
- Comparte comportamiento e implementación.
- Relación "es un" fuerte.
- Solo una superclase.
- Heredas el código de la clase padre.
### `implements` (Interfaz)
- Comparte solo la firma (API).
- Relación "se comporta como".
- Múltiples interfaces.
- Debes escribir tu propia implementación de todo.
```dart
class Engine {
void start() => print('Engine started');
}
// Herencia: Car TIENE el código de start()
class Car extends Engine {}
// Interfaz: SmartCar DEBE implementar start()
class SmartCar implements Engine {
@override
void start() {
print('Smart engine booting sequence...');
}
}
```
## Casos de Uso en Flutter
### 1. Mocking en Tests
Las interfaces implícitas hacen que el mocking sea trivial en Dart. Puedes crear un mock de *cualquier* clase implementándola.
```dart
class ApiService {
Future fetchData() async {
// Llamada real a red compleja
return 'Real Data';
}
}
// En tus tests
class MockApiService implements ApiService {
@override
Future fetchData() async {
return 'Test Data';
}
}
void main() {
test('should use mock data', () async {
final api = MockApiService(); // Polimorfismo
expect(await api.fetchData(), 'Test Data');
});
}
```
### 2. Protocolos de Delegación
Similar a iOS, puedes definir interfaces para delegar acciones.
```dart
abstract class SelectionListener {
void onItemSelected(String item);
}
class ListWidget {
final SelectionListener listener;
ListWidget(this.listener);
void tapItem(String item) {
listener.onItemSelected(item);
}
}
```
## Combinando Interfaces
Puedes implementar múltiples interfaces para crear objetos con capacidades compuestas.
```dart
abstract class JSONSerializable {
Map toJson();
}
abstract class Copyable {
T copy();
}
class User implements JSONSerializable, Copyable {
final String name;
User(this.name);
@override
Map toJson() => {'name': name};
@override
User copy() => User(name);
}
```
## Conclusión
El sistema de interfaces implícitas de Dart es poderoso y flexible.
- No necesitas declarar `interface MyInterface`.
- Usa `abstract class` para definir contratos.
- Usa `implements` para cumplir contratos.
- Usa `implements` para mocks y tests.
Este apartado profundiza en los conceptos clave, proporcionando ejemplos prácticos y mejores prácticas para su aplicación en proyectos reales.
Al comprender estos detalles, podrás diseñar soluciones más robustas, mantenibles y escalables en tus aplicaciones Flutter y Dart.