Herencia básica
Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy. Lección 36 de 110.
La herencia permite que una clase adquiera las propiedades y métodos de otra clase. En lugar de volver a escribir el mismo código, se crea una nueva clase que se basa en una ya existente. La clase original se llama padre (o superclase), y la nueva clase es la hija (o subclase).
En Dart, usas la palabra clave extends para heredar de una clase padre:
class Animal {
String name;
Animal(this.name);
void eat() {
print('$name is eating');
}
}
class Dog extends Animal {
Dog(String name) : super(name);
void bark() {
print('$name says woof!');
}
}
void main() {
var dog = Dog('Buddy');
dog.eat(); // Heredado de Animal
dog.bark(); // Definido en Dog
}La clase Dog tiene automáticamente acceso a la propiedad name y al método eat() de Animal, además de su propio método bark(). Esto crea una relación de «es-un»: un Dog es un Animal.
La clase hija puede añadir nuevas propiedades y métodos, pero hereda todo lo público del padre. Ten en cuenta que los miembros privados (aquellos con _) no son accesibles directamente en subclases de diferentes librerías, aunque sigan existiendo en el objeto heredado.
Desafío
FácilConstruyamos un sistema de vehículos que demuestre cómo la herencia permite que las clases hijas reutilicen y amplíen la funcionalidad de la clase padre. Crearás una clase padre para vehículos generales y una clase hija para un tipo específico de vehículo.
Organizarás tu código en dos archivos:
vehicle.dart: Define aquí tus clases:- Una clase
Vehicle(la clase padre) con una propiedadString brand, un constructor que recibe la marca y un métodostart()que imprime[brand] engine starting... - Una clase
Motorcycleque extiendeVehicle. Debe tener una propiedad adicionalint cc(cilindrada del motor), un constructor que recibe tanto la marca como cc (pasando la marca a la clase padre mediantesuper) y su propio métodowheelie()que imprime[brand] is doing a wheelie!
- Una clase
main.dart: Importa tu archivo de vehículos y demuestra la herencia en acción:- Crea un
Vehiclecon la marca'Toyota' - Llama a su método
start() - Crea una
Motorcyclecon la marca'Harley'y cc1200 - Llama al método
start()de la motocicleta (heredado de Vehicle) - Llama al método
wheelie()de la motocicleta (definido en Motorcycle) - Imprime
Motorcycle engine: [cc]ccpara mostrar la propiedad propia de la clase hija
- Crea un
Observa cómo la clase Motorcycle obtiene automáticamente acceso a la propiedad brand y al método start() de Vehicle, además de tener su propia propiedad única cc y su propio método wheelie(). Este es el poder de la herencia: construir sobre código existente.
Salida esperada:
Toyota engine starting...
Harley engine starting...
Harley is doing a wheelie!
Motorcycle engine: 1200ccPruébalo tú mismo
import 'vehicle.dart';
void main() {
// TODO: Crea un Vehicle con brand 'Toyota'
// TODO: Llama al método start() del vehículo
// TODO: Crea una Motorcycle con brand 'Harley' y cc 1200
// TODO: Llama al método start() de la motocicleta (heredado de Vehicle)
// TODO: Llama al método wheelie() de la motocicleta
// TODO: Imprime 'Motorcycle engine: [cc]cc' usando la propiedad cc de la motocicleta
}
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 RepositoryPractica por tu cuenta: Compilador de Dart online