Constructores y herencia
Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy — lección 41 de 110.
Cuando una clase hija extiende a una madre, se debe llamar al constructor de la madre para inicializar correctamente los campos heredados. Dart proporciona formas flexibles de manejar esto a través de la lista de inicializadores usando super.
Si el padre tiene un constructor parametrizado, el hijo debe llamarlo explícitamente:
class Person {
String name;
int age;
Person(this.name, this.age);
}
class Student extends Person {
String school;
Student(String name, int age, this.school) : super(name, age);
}Dart 2.17 introdujo los superparámetros, una sintaxis más limpia que reenvía los parámetros directamente al constructor padre:
class Student extends Person {
String school;
// super.name y super.age se reenvían directamente al constructor de Person
Student(super.name, super.age, this.school);
}Al trabajar con constructores con nombre, especificas a qué constructor padre llamar:
class Employee extends Person {
String department;
Employee(super.name, super.age, this.department);
Employee.intern(String name, this.department) : super(name, 18);
}La regla clave es sencilla: el padre debe estar completamente inicializado antes de que el hijo añada sus propias propiedades. Ya sea que uses la llamada tradicional super() o los nuevos parámetros super, Dart garantiza que la cadena de herencia se construya correctamente de padre a hijo.
Desafío
FácilVamos a construir un sistema de inventario de productos que demuestre cómo funcionan los constructores con la herencia. Crearás una jerarquía donde diferentes tipos de productos extienden una clase base de producto, cada uno requiriendo una inicialización adecuada a través de los constructores padres.
Organizarás tu código en dos archivos:
product.dart: Define tu jerarquía de productos aquí:- Una clase
Productcon las propiedadesString nameydouble price, un constructor que toma ambos valores, y un métodoinfo()que imprime[name]: $[price] - Una clase
Bookque extiendeProducty añade una propiedadString author. Usa parámetros super para reenviarnameypriceal constructor padre - Una clase
Electronicsque extiendeProducty añade una propiedadint warranty(en meses). Usa la llamada tradicionalsuper()en la lista de inicializadores para pasar los valores al padre
- Una clase
main.dart: Importa tu archivo de productos y demuestra ambos enfoques de herencia de constructores:- Crea un
Bookcon name'Dart Essentials', price29.99, y author'Jane Smith' - Llama a su método
info(), luego imprimeAuthor: [author] - Imprime una línea vacía
- Crea un
Electronicscon name'Wireless Mouse', price45.50, y warranty24 - Llama a su método
info(), luego imprimeWarranty: [warranty] months
- Crea un
Ambas clases hijas heredan el método info() de Product sin necesidad de sobrescribirlo. La diferencia clave está en cómo llaman al constructor padre: Book utiliza la sintaxis más limpia de parámetros super, mientras que Electronics utiliza el enfoque tradicional con super() en la lista de inicializadores.
Salida esperada:
Dart Essentials: $29.99
Author: Jane Smith
Wireless Mouse: $45.5
Warranty: 24 monthsHoja de referencia
Cuando una clase hija extiende a una madre, se debe llamar al constructor de la madre para inicializar correctamente los campos heredados.
Enfoque tradicional - llamar explícitamente al constructor padre en la lista de inicializadores:
class Person {
String name;
int age;
Person(this.name, this.age);
}
class Student extends Person {
String school;
Student(String name, int age, this.school) : super(name, age);
}Parámetros super (Dart 2.17+) - reenviar parámetros directamente al constructor padre:
class Student extends Person {
String school;
Student(super.name, super.age, this.school);
}Constructores nombrados - especificar a qué constructor padre llamar:
class Employee extends Person {
String department;
Employee(super.name, super.age, this.department);
Employee.intern(String name, this.department) : super(name, 18);
}Pruébalo tú mismo
import 'product.dart';
void main() {
// TODO: Crear un Book con:
// - name: 'Dart Essentials'
// - price: 29.99
// - author: 'Jane Smith'
// TODO: Llamar al método info() del book
// TODO: Imprimir "Author: [author]"
// TODO: Imprimir una línea vacía
// TODO: Crear un Electronics con:
// - name: 'Wireless Mouse'
// - price: 45.50
// - warranty: 24
// TODO: Llamar al método info() del electronics
// TODO: Imprimir "Warranty: [warranty] months"
}
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