Menu
Coddy logo textTech

Mixin vs Interfaz

Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy. Lección 55 de 110.

Has visto cómo se comparan los mixins con la herencia. Ahora comparemos los mixins con las interfaces, ya que ambos permiten trabajar con múltiples tipos. La diferencia clave es lo que proporcionan: las interfaces definen un contrato, mientras que los mixins proporcionan una implementación.

Cuando implementas una interfaz, te comprometes a proporcionar ciertos métodos, pero escribes todo el código tú mismo. Cuando usas un mixin, obtienes el código real gratis.

// Enfoque de interfaz: debes implementar todo
abstract class Printable {
  void printInfo();
}

class Report implements Printable {
  @override
  void printInfo() {
    print('Printing report...');  // Tú escribes esto
  }
}

// Enfoque de mixin: implementación incluida
mixin Printable {
  void printInfo() {
    print('Printing...');  // Ya escrito para ti
  }
}

class Report with Printable {}  // Obtiene printInfo() automáticamente

Entonces, ¿cuándo deberías usar cada uno? Usa una interfaz cuando distintas clases necesiten las mismas firmas de métodos, pero implementaciones diferentes. Usa un mixin cuando las clases deban compartir exactamente el mismo comportamiento.

CaracterísticaInterfazMixin
ProporcionaSolo contratoContrato + código
ImplementaciónLa escribes túIncluida
Palabra claveimplementswith
Mejor paraComportamientos diferentes, misma APIComportamiento compartido

Incluso puedes combinar ambos enfoques: usa interfaces para definir lo que una clase puede hacer y mixins para proporcionar implementaciones comunes cuando sea apropiado. En Dart, al combinar ambos, coloca siempre with antes de implements:

class MyClass with SomeMixin implements SomeInterface {
  // with va antes de implements
}
challenge icon

Desafío

Fácil

Construyamos un sistema de notificaciones que demuestre cuándo usar interfaces en lugar de mixins. Crearás una interfaz para las notificaciones que requieren implementaciones diferentes y un mixin para el comportamiento de registro compartido que debe ser idéntico en todos los tipos de notificación.

Organizarás tu código en tres archivos:

  • notifiable.dart: Define una clase abstracta Notifiable que actúa como una interfaz. Debe declarar dos métodos abstractos: send(String message) y getChannel(), que devuelve un String. Los distintos tipos de notificación implementarán estos métodos de manera diferente según su canal específico.
  • logging.dart: Crea un mixin Logging que proporcione el comportamiento compartido que todas las notificaciones deben tener. Incluye un método logSent(String channel, String message) que muestre [LOG] Sent via [channel]: [message] y un método logTimestamp() que muestre [LOG] Timestamp recorded. Este comportamiento es idéntico para todos los tipos de notificación, por lo que es perfecto para un mixin.
  • main.dart: Importa ambos archivos y crea dos clases de notificación que combinen la interfaz con el mixin:
    • Una clase EmailNotification que use el mixin Logging e implemente Notifiable. Su método getChannel() debe devolver 'Email', y su método send() debe mostrar Sending email: [message], después llamar a logSent() con el canal y el mensaje, y después llamar a logTimestamp()
    • Una clase SMSNotification que use el mixin Logging e implemente Notifiable. Su método getChannel() debe devolver 'SMS', y su método send() debe mostrar Sending SMS: [message], después llamar a logSent() con el canal y el mensaje, y después llamar a logTimestamp()
    Después crea un EmailNotification y llama a send('Hello World'), muestra una línea vacía, crea un SMSNotification y llama a send('Quick update')

Observa cómo la interfaz obliga a cada clase a escribir sus propias implementaciones de send() y getChannel() (comportamiento diferente), mientras que el mixin proporciona los métodos de registro que funcionan de manera idéntica para ambas (comportamiento compartido).

Salida esperada:

Sending email: Hello World
[LOG] Sent via Email: Hello World
[LOG] Timestamp recorded

Sending SMS: Quick update
[LOG] Sent via SMS: Quick update
[LOG] Timestamp recorded

Pruébalo tú mismo

import 'notifiable.dart';
import 'logging.dart';

// TODO: Crear la clase EmailNotification que:
//       - use el mixin Logging (with)
//       - implemente Notifiable (implements)
//       - getChannel() devuelva 'Email'
//       - send() imprima 'Sending email: [message]', luego llame a logSent(), y después a logTimestamp()

// TODO: Crear la clase SMSNotification que:
//       - use el mixin Logging (with)
//       - implemente Notifiable (implements)
//       - getChannel() devuelva 'SMS'
//       - send() imprima 'Sending SMS: [message]', luego llame a logSent(), y después a logTimestamp()

void main() {
  // TODO: Crear una EmailNotification y llamar a send('Hello World')
  
  // TODO: Imprimir una línea vacía
  
  // TODO: Crear una SMSNotification y llamar a send('Quick update')
}
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

Practica por tu cuenta: Compilador de Dart online