# Polimorfismo y Herencia en Dart
El polimorfismo es la capacidad de tratar objetos de diferentes clases de manera uniforme si comparten una superclase o interfaz común.
## Herencia (`extends`)
Permite crear una nueva clase basada en una existente, heredando sus propiedades y métodos.
```dart
class Animal {
void makeSound() => print('Generic sound');
}
class Dog extends Animal {
@override
void makeSound() => print('Woof!');
}
class Cat extends Animal {
@override
void makeSound() => print('Meow!');
}
```
## Polimorfismo en Acción
Puedes usar una variable de tipo `Animal` para referenciar instancias de `Dog` o `Cat`.
```dart
void playSound(Animal animal) {
// No sabemos si es Dog o Cat, pero sabemos que es Animal
// El método ejecutado depende de la instancia real (Runtime Type)
animal.makeSound();
}
void main() {
List zoo = [Dog(), Cat(), Dog()];
for (final animal in zoo) {
playSound(animal);
}
// Output:
// Woof!
// Meow!
// Woof!
}
```
## Constructores y `super`
Los constructores no se heredan, pero deben invocarse.
```dart
class Person {
final String name;
Person(this.name);
Person.anonymous() : name = 'Anonymous';
}
class Employee extends Person {
final String department;
// Llamada explícita al constructor padre
Employee(String name, this.department) : super(name);
// Llamada a constructor nombrado padre
Employee.temp(this.department) : super.anonymous();
}
```
## `covariant` Keyword
A veces necesitas sobrescribir un método pero estrechando el tipo de parámetro. Dart permite esto con `covariant`.
```dart
class Animal {
void chase(Animal x) {}
}
class Mouse extends Animal {}
class Cat extends Animal {
// Normalmente esto sería un error porque la firma debe coincidir
// Pero con 'covariant' permitimos que Cat solo persiga Mouse
@override
void chase(covariant Mouse x) {
print('Cat chasing mouse');
}
}
void main() {
final cat = Cat();
cat.chase(Mouse()); // OK
// cat.chase(Dog()); // Error en tiempo de compilación o ejecución
}
```
## Polimorfismo con Interfaces
El polimorfismo funciona igual con `implements`.
```dart
abstract class Logger {
void log(String msg);
}
class ConsoleLogger implements Logger {
@override
void log(String msg) => print('Console: $msg');
}
class FileLogger implements Logger {
@override
void log(String msg) => print('File: Writing "$msg" to disk');
}
class App {
final Logger logger; // Polimorfismo: Acepta cualquier Logger
App(this.logger);
void run() {
logger.log('App started');
}
}
```
## Beneficios en Flutter
El polimorfismo es fundamental en Flutter. Todo es un `Widget`.
```dart
// El método build devuelve Widget, pero puedes retornar
// Container, Column, Text, etc. porque todos son Widgets.
Widget build(BuildContext context) {
return Container();
}
// Las listas de hijos aceptan List
Column(
children: [
Text('Hello'), // Es un Widget
ElevatedButton(), // Es un Widget
MyCustomWidget(), // Es un Widget
],
)
```
## Conclusión
El polimorfismo permite escribir código:
- **Flexible**: Funciona con nuevas clases sin modificar el código existente.
- **Reutilizable**: Lógica común en la clase base.
- **Extensible**: Fácil de agregar nuevas implementaciones.
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.