La anotación @override
Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy — lección 39 de 110.
La anotación @override es un marcador de mejores prácticas que le indica a Dart (y a otros desarrolladores) que estás reemplazando intencionalmente un método de una clase padre. Aunque la sobrescritura de métodos funciona sin ella, usar @override añade una red de seguridad importante.
class Animal {
String name;
Animal(this.name);
void speak() {
print('$name makes a sound');
}
}
class Dog extends Animal {
Dog(String name) : super(name);
@override
void speak() {
print('$name barks: Woof!');
}
}La anotación proporciona dos beneficios clave. Primero, documenta tu intención claramente: cualquier persona que lea el código sabrá de inmediato que este método existe en la clase padre. Segundo, el analizador de Dart te advertirá si el método padre no existe realmente, detectando errores tipográficos y errores de refactorización a tiempo.
Considera qué sucede si escribes mal el nombre del método sin @override:
class Cat extends Animal {
Cat(String name) : super(name);
void speek() { // ¡Error tipográfico! Sin advertencia sin @override
print('$name meows');
}
}Sin la anotación, Dart asume que estás creando un nuevo método llamado speek(). Con @override, el analizador señalaría inmediatamente que no existe tal método en la clase padre. Esta simple anotación evita errores sutiles que pueden ser difíciles de rastrear más adelante.
Desafío
FácilVamos a construir un sistema de reproductor de medios que demuestre la importancia de la anotación @override al personalizar el comportamiento heredado. Crearás diferentes tipos de medios que cada uno reproduce contenido a su propia manera.
Organizarás tu código en dos archivos:
media.dart: Define tu jerarquía de medios aquí:- Una clase
Mediacon una propiedadString title, un constructor que recibe el título y un métodoplay()que imprimePlaying: [title] - Una clase
Songque extiende deMediay añade una propiedadString artist. Usa la anotación@overridey sobrescribeplay()para imprimirPlaying song: [title] by [artist] - Una clase
Videoque extiende deMediay añade una propiedadint duration(en segundos). Usa@overridey sobrescribeplay()para llamar primero a la versión del padre consuper.play(), y luego imprimirDuration: [duration] seconds
- Una clase
main.dart: Importa tu archivo de medios y demuestra los métodos sobrescritos:- Crea un objeto
Mediacon el título'Generic Content'y llama aplay() - Imprime una línea vacía
- Crea un
Songcon el título'Imagine'y el artista'John Lennon', luego llama aplay() - Imprime una línea vacía
- Crea un
Videocon el título'Dart Tutorial'y la duración360, luego llama aplay()
- Crea un objeto
La anotación @override documenta tu intención y ayuda a detectar errores. Si accidentalmente escribieras mal play() como plya(), la anotación te alertaría de que no existe tal método en la clase padre.
Salida esperada:
Playing: Generic Content
Playing song: Imagine by John Lennon
Playing: Dart Tutorial
Duration: 360 secondsHoja de referencia
La anotación @override marca los métodos que reemplazan intencionalmente un método de la clase padre. Aunque es opcional, proporciona seguridad y claridad.
class Animal {
String name;
Animal(this.name);
void speak() {
print('$name makes a sound');
}
}
class Dog extends Animal {
Dog(String name) : super(name);
@override
void speak() {
print('$name barks: Woof!');
}
}Beneficios de @override:
- Documenta la intención: muestra que el método existe en la clase padre
- Detecta errores: el analizador de Dart advierte si el método padre no existe, evitando errores de escritura
Sin @override, los errores de escritura crean nuevos métodos en lugar de señalar errores:
class Cat extends Animal {
Cat(String name) : super(name);
void speek() { // El error de escritura crea un nuevo método sin previo aviso
print('$name meows');
}
}Puedes llamar a la versión del padre usando super:
@override
void play() {
super.play(); // Llama primero al método padre
print('Additional behavior');
}Pruébalo tú mismo
import 'media.dart';
void main() {
// TODO: Crear un objeto Media con el título 'Generic Content' y llamar a play()
// TODO: Imprimir una línea vacía
// TODO: Crear un Song con el título 'Imagine' y el artista 'John Lennon', luego llamar a play()
// TODO: Imprimir una línea vacía
// TODO: Crear un Video con el título 'Dart Tutorial' y la duración 360, luego llamar a play()
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de POO
Archivos externosLibrerías e importacionesIntroducción a la POOClases vs. ObjetosLa palabra clave thisMétodosVariables de instanciaConceptos básicos de constructoresResumen - Calculadora sencilla4Seguridad de nulos
Introducción a la seguridad de nulosNulables vs No nulablesLos operadores ? y !Palabra clave Late y Null SafetyOperadores Null-awareNull Safety en clasesResumen - Sistema de perfil de usuario7Clases abstractas e interfaces
Clases abstractasMétodos abstractosInterfaces en DartInterfaces implícitasImplementar vs. ExtenderInterfaces múltiplesRepaso - Calculadora de figuras10Colecciones y Genéricos
Visión general de List, Set y MapColecciones con seguridad de tiposClases genéricasMétodos genéricosRestricciones genéricasIterable e IteratorResumen - Almacenamiento genérico2Constructores en Dart
Constructor por defectoConstructores nombradosListas de inicializaciónConstructores constantesConstructores de fábricaConstructores de redireccionamientoResumen - Constructor de formas5Encapsulamiento
Miembros públicos vs. privadosLa convención del prefijo _Privacidad a nivel de libreríaProfundidad en Getters y SettersOcultamiento de informaciónResumen - Registros de estudiantes8Mixins
Introducción a los MixinsCreación de MixinsUso de múltiples MixinsPalabra clave on en MixinsMixin vs HerenciaMixin vs InterfazResumen - Sistema Animal11Métodos especiales
Sobrescritura de toString()Sobrescritura de hashCode y ==Interfaz ComparableMétodo call()Sobrescritura de noSuchMethodResumen - Colección personalizada14Patrones de diseño Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón Strategy3Propiedades de clase
Miembros de instancia vs. estáticosCampos Final y ConstVariables LateMétodos y campos estáticosGetters y SettersResumen - Gestor de cuentas bancarias6Herencia
Herencia básicaLa palabra clave superSobrescritura de métodosLa anotación @overrideLa palabra clave final en clasesConstructores y herenciaResumen - Jerarquía de empleados9Polimorfismo
Fundamentos del polimorfismoPolimorfismo mediante interfacesComprobación de tipos en tiempo de ejecuciónLos operadores is y asPalabra clave covariantResumen - Procesador de pagos12POO Asíncrona
Futures y async/awaitFundamentos de StreamsStream ControllersConstructores asíncronosAsincronía en métodos de claseRepaso - Data Fetcher15Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Repository