Creación de Mixins
Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy — lección 51 de 110.
Ahora que entiendes qué son los mixins, veamos cómo crearlos correctamente. Un mixin se declara utilizando la palabra clave mixin en lugar de class.
mixin Logging {
void log(String message) {
print('[LOG] $message');
}
void logError(String error) {
print('[ERROR] $error');
}
}Los mixins pueden contener métodos, propiedades e incluso getters y setters, al igual que las clases. Sin embargo, hay una regla importante: los mixins no pueden tener constructores. Dado que los mixins están destinados a ser "mezclados" en lugar de ser instanciados directamente, no necesitan lógica de inicialización.
mixin Timestamped {
DateTime createdAt = DateTime.now();
String get formattedTime => createdAt.toString();
void printTimestamp() {
print('Created at: $formattedTime');
}
}
class Document with Timestamped {
String title;
Document(this.title);
}
void main() {
var doc = Document('Report');
doc.printTimestamp(); // Utiliza el método del mixin
print(doc.createdAt); // Utiliza la propiedad del mixin
}Cuando aplicas un mixin con with, todos sus miembros pasan a formar parte de tu clase. La clase puede usarlos directamente, y también puede hacerlo cualquier código que tenga una instancia de esa clase. Esto hace que los mixins sean una forma limpia de añadir funcionalidad reutilizable sin la complejidad de las jerarquías de herencia.
Desafío
FácilVamos a construir un sistema de mensajería que muestre cómo crear mixins con métodos, propiedades y getters. Diseñarás un mixin que añade capacidades de formateo a diferentes tipos de mensajes.
Organizarás tu código en dos archivos:
messaging.dart: Define tu mixin y las clases de mensaje aquí:- Un mixin
Formattableque contiene:- Una propiedad
String prefixinicializada en'>>>' - Un getter
separatorque devuelve' | ' - Un método
format(String text)que devuelve el string[prefix][separator][text] - Un método
formatBold(String text)que devuelve**[text]**
- Una propiedad
- Una clase
TextMessageque utiliza el mixinFormattable. Añade una propiedadString sendercon un constructor. Incluye un métodosend(String content)que imprima el resultado de llamar aformat()con[sender]: [content] - Una clase
AlertMessageque también utiliza el mixinFormattable. Añade una propiedadString levelcon un constructor. Incluye un métodoalert(String content)que imprima el resultado de llamar aformat()con[[level]] [formatBold(content)]
- Un mixin
main.dart: Importa tu archivo de mensajería y demuestra cómo ambos tipos de mensaje obtienen capacidades de formateo del mixin:- Crea un
TextMessagecon sender'Alice' - Crea un
AlertMessagecon level'WARNING' - Llama a
send('Hello there!')en el mensaje de texto - Llama a
alert('System overload')en el mensaje de alerta
- Crea un
Tu mixin demuestra que los mixins pueden contener propiedades con valores por defecto, getters que calculan valores y múltiples métodos que incluso pueden llamarse entre sí. Ambas clases de mensaje obtienen toda esta funcionalidad simplemente usando la palabra clave with.
Salida esperada:
>>> | Alice: Hello there!
>>> | [WARNING] **System overload**Hoja de referencia
Los mixins se declaran utilizando la palabra clave mixin en lugar de class:
mixin Logging {
void log(String message) {
print('[LOG] $message');
}
void logError(String error) {
print('[ERROR] $error');
}
}Los mixins pueden contener métodos, propiedades, getters y setters, pero no pueden tener constructores:
mixin Timestamped {
DateTime createdAt = DateTime.now();
String get formattedTime => createdAt.toString();
void printTimestamp() {
print('Created at: $formattedTime');
}
}Aplica mixins a las clases utilizando la palabra clave with. Todos los miembros del mixin pasan a formar parte de la clase:
class Document with Timestamped {
String title;
Document(this.title);
}
void main() {
var doc = Document('Report');
doc.printTimestamp(); // Usa el método del mixin
print(doc.createdAt); // Usa la propiedad del mixin
}Pruébalo tú mismo
import 'messaging.dart';
void main() {
// TODO: Crea un TextMessage con el remitente 'Alice'
// TODO: Crea un AlertMessage con el nivel 'WARNING'
// TODO: Llama a send('Hello there!') en el mensaje de texto
// TODO: Llama a alert('System overload') en el mensaje de alerta
}
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