Menu
Coddy logo textTech

Introducción a los Mixins

Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy — lección 50 de 110.

Has aprendido que Dart solo permite extender una clase y, aunque puedes implementar múltiples interfaces, debes escribir todo el código tú mismo. ¿Pero qué pasa si quieres compartir código de implementación real entre múltiples clases no relacionadas? Aquí es donde entran los mixins.

Un mixin es una forma de reutilizar código en múltiples jerarquías de clases. Piénsalo como un conjunto de métodos y propiedades que puedes "mezclar" en cualquier clase, otorgándole nuevas capacidades sin utilizar la herencia.

mixin Swimming {
  void swim() {
    print('Swimming through the water');
  }
}

class Duck with Swimming {
  void quack() {
    print('Quack!');
  }
}

class Fish with Swimming {
  void blowBubbles() {
    print('Blub blub');
  }
}

void main() {
  var duck = Duck();
  duck.quack();
  duck.swim();  // Desde el mixin
  
  var fish = Fish();
  fish.swim();  // Misma implementación, diferente clase
}

Observa la palabra clave with: así es como aplicas un mixin a una clase. A diferencia de implements, no necesitas escribir el método tú mismo. El mixin proporciona el código real y tu clase obtiene esa funcionalidad automáticamente.

Los mixins resuelven un problema real: Duck y Fish no están relacionados mediante herencia, pero ambos necesitan el comportamiento de nadar. Con los mixins, escribes el código una vez y lo compartes donde sea necesario.

challenge icon

Desafío

Fácil

Vamos a construir un sistema de instrumentos musicales que demuestre cómo los mixins permiten compartir comportamientos entre clases no relacionadas. Crearás un mixin que proporcione funcionalidad de afinación y luego lo aplicarás a diferentes instrumentos que no están relacionados mediante herencia.

Organizarás tu código en dos archivos:

  • instruments.dart: Define aquí tu mixin y las clases de instrumentos:
    • Un mixin Tunable con un método tune() que imprima Tuning the instrument... y un método checkTuning() que imprima Tuning is perfect!
    • Una clase Guitar que use el mixin Tunable. Añade una propiedad String brand con un constructor. Incluye un método strum() que imprima [brand] guitar strumming chords
    • Una clase Piano que también use el mixin Tunable. Añade una propiedad int keys con un constructor. Incluye un método play() que imprima Playing [keys]-key piano
  • main.dart: Importa tu archivo de instrumentos y demuestra cómo ambos instrumentos no relacionados obtienen capacidades de afinación del mismo mixin:
    • Crea una Guitar con la marca 'Fender'
    • Crea un Piano con 88 teclas
    • Para la guitarra: llama a tune(), luego a strum(), y después a checkTuning()
    • Imprime una línea vacía
    • Para el piano: llama a tune(), luego a play(), y después a checkTuning()

Observa cómo Guitar y Piano son instrumentos completamente diferentes sin relación de herencia, y aun así ambos obtienen exactamente los mismos métodos de afinación del mixin Tunable. Escribes el código de afinación una vez, y ambas clases pueden usarlo con la palabra clave with.

Salida esperada:

Tuning the instrument...
Fender guitar strumming chords
Tuning is perfect!

Tuning the instrument...
Playing 88-key piano
Tuning is perfect!

Hoja de referencia

Un mixin es una forma de reutilizar código en múltiples clases no relacionadas sin utilizar la herencia. Es un conjunto de métodos y propiedades que puedes "mezclar" (mix into) en cualquier clase.

Define un mixin utilizando la palabra clave mixin:

mixin Swimming {
  void swim() {
    print('Swimming through the water');
  }
}

Aplica un mixin a una clase utilizando la palabra clave with:

class Duck with Swimming {
  void quack() {
    print('Quack!');
  }
}

class Fish with Swimming {
  void blowBubbles() {
    print('Blub blub');
  }
}

A diferencia de implements, no necesitas escribir la implementación del método tú mismo: el mixin proporciona el código real y tu clase adquiere esa funcionalidad automáticamente.

Tanto Duck como Fish pueden ahora usar el método swim() aunque no estén relacionados a través de la herencia:

var duck = Duck();
duck.swim();  // From the mixin

var fish = Fish();
fish.swim();  // Same implementation, different class

Pruébalo tú mismo

import 'instruments.dart';

void main() {
  // TODO: Crear una Guitarra con la marca 'Fender'
  
  // TODO: Crear un Piano con 88 teclas
  
  // TODO: Para la guitarra: llamar a tune(), luego strum(), luego checkTuning()
  
  // TODO: Imprimir una línea vacía
  
  // TODO: Para el piano: llamar a tune(), luego play(), luego checkTuning()
}
quiz iconPonte a prueba

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