Clases abstractas
Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy — lección 43 de 110.
Una clase abstracta es una clase que no se puede instanciar directamente. Sirve como un plano para otras clases, definiendo una estructura común que las subclases deben seguir. Se crea una utilizando la palabra clave abstract.
abstract class Shape {
String color;
Shape(this.color);
void describe() {
print('A $color shape');
}
}
class Circle extends Shape {
double radius;
Circle(String color, this.radius) : super(color);
}
void main() {
// Shape s = Shape('red'); // ¡Error! No se puede instanciar una clase abstracta
var circle = Circle('blue', 5.0);
circle.describe(); // Una forma blue
}Las clases abstractas son útiles cuando tienes un concepto que es demasiado general para existir por sí solo. Una "Shape" es una idea, pero no puedes dibujar una forma sin saber si es un círculo, un rectángulo o un triángulo. La clase abstracta define lo que todas las formas tienen en común, mientras que las subclases concretas proporcionan los detalles específicos.
Ten en cuenta que las clases abstractas aún pueden tener métodos regulares con implementaciones (como describe()) y constructores. Las subclases heredan estos de la misma manera que con la herencia normal. La diferencia clave es simplemente que no puedes crear una instancia de la propia clase abstracta; debes usar una subclase concreta.
Desafío
FácilVamos a construir un sistema de vehículos que demuestre cómo las clases abstractas sirven como planos para tipos más específicos. Crearás una clase base abstracta que defina lo que todos los vehículos tienen en común y luego la extenderás con tipos de vehículos concretos.
Organizarás tu código en dos archivos:
vehicle.dart: Define tu jerarquía de vehículos aquí:- Una
abstract class Vehiclecon una propiedadString brandy una propiedadint year. Incluye un constructor que tome ambos valores y un métododisplayInfo()que imprima[brand] ([year]) - Una clase
Carque extiendaVehicley añada una propiedadint doors. Incluye un métodohonk()que imprimaBeep beep! - Una clase
Motorcycleque extiendaVehicley añada una propiedadbool hasSidecar. Incluye un métodorevEngine()que imprimaVroom!
- Una
main.dart: Importa tu archivo de vehículos y demuestra cómo funcionan las clases abstractas:- Crea un
Carcon brand'Toyota', year2022, y doors4 - Llama a su método
displayInfo()(heredado de Vehicle) - Imprime
Doors: [doors] - Llama a su método
honk() - Imprime una línea vacía
- Crea una
Motorcyclecon brand'Harley', year2021, y hasSidecarfalse - Llama a su método
displayInfo() - Imprime
Has sidecar: [hasSidecar] - Llama a su método
revEngine()
- Crea un
Recuerda que no puedes crear una instancia de Vehicle directamente ya que es abstracta; debes usar una de las subclases concretas. Tanto Car como Motorcycle heredan el método displayInfo() de la clase padre abstracta.
Salida esperada:
Toyota (2022)
Doors: 4
Beep beep!
Harley (2021)
Has sidecar: false
Vroom!Hoja de referencia
Una clase abstracta es una clase que no se puede instanciar directamente. Sirve como un modelo para otras clases, definiendo una estructura común que las subclases deben seguir. Crea una usando la palabra clave abstract:
abstract class Shape {
String color;
Shape(this.color);
void describe() {
print('A $color shape');
}
}
class Circle extends Shape {
double radius;
Circle(String color, this.radius) : super(color);
}
void main() {
// Shape s = Shape('red'); // ¡Error! No se puede instanciar una clase abstracta
var circle = Circle('blue', 5.0);
circle.describe(); // A blue shape
}Las clases abstractas pueden tener:
- Métodos regulares con implementaciones
- Constructores
- Propiedades
Las subclases heredan estos miembros al igual que con la herencia normal. La diferencia clave es que no se puede crear una instancia de la propia clase abstracta; se debe utilizar una subclase concreta.
Pruébalo tú mismo
import 'vehicle.dart';
void main() {
// TODO: Crear un Car con marca 'Toyota', año 2022 y puertas 4
// TODO: Llamar a displayInfo() en el car
// TODO: Imprimir "Doors: [doors]"
// TODO: Llamar a honk() en el car
// TODO: Imprimir una línea vacía
// TODO: Crear una Motorcycle con marca 'Harley', año 2021 y hasSidecar false
// TODO: Llamar a displayInfo() en la motorcycle
// TODO: Imprimir "Has sidecar: [hasSidecar]"
// TODO: Llamar a revEngine() en la motorcycle
}
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