Menu
Coddy logo textTech

Introdução aos Mixins

Parte da seção Programação Orientada a Objetos do Journey de Dart da Coddy — lição 50 de 110.

Você aprendeu que o Dart permite estender apenas uma classe e, embora você possa implementar múltiplas interfaces, deve escrever todo o código por conta própria. Mas e se você quiser compartilhar o código de implementação real entre várias classes não relacionadas? É aqui que os mixins entram.

Um mixin é uma forma de reutilizar código em múltiplas hierarquias de classes. Pense nele como um conjunto de métodos e propriedades que você pode "misturar" em qualquer classe, fornecendo a ela novas capacidades sem usar herança.

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();  // Vindo do mixin
  
  var fish = Fish();
  fish.swim();  // Mesma implementação, classe diferente
}

Observe a palavra-chave with - é assim que você aplica um mixin a uma classe. Ao contrário de implements, você não precisa escrever o método por conta própria. O mixin fornece o código real e sua classe ganha essa funcionalidade automaticamente.

Mixins resolvem um problema real: Duck e Fish não estão relacionados por herança, mas ambos precisam de comportamento de natação. Com mixins, você escreve o código uma vez e o compartilha onde quer que seja necessário.

challenge icon

Desafio

Fácil

Vamos construir um sistema de instrumentos musicais que demonstra como os mixins permitem compartilhar comportamento entre classes não relacionadas. Você criará um mixin que fornece funcionalidade de afinação e, em seguida, o aplicará a diferentes instrumentos que não estão relacionados por herança.

Você organizará seu código em dois arquivos:

  • instruments.dart: Defina seu mixin e as classes de instrumentos aqui:
    • Um mixin Tunable com um método tune() que imprime Tuning the instrument... e um método checkTuning() que imprime Tuning is perfect!
    • Uma classe Guitar que usa o mixin Tunable. Adicione uma propriedade String brand com um construtor. Inclua um método strum() que imprime [brand] guitar strumming chords
    • Uma classe Piano que também usa o mixin Tunable. Adicione uma propriedade int keys com um construtor. Inclua um método play() que imprime Playing [keys]-key piano
  • main.dart: Importe seu arquivo de instrumentos e demonstre como ambos os instrumentos não relacionados ganham recursos de afinação do mesmo mixin:
    • Crie um Guitar com a marca 'Fender'
    • Crie um Piano com 88 teclas
    • Para a guitarra: chame tune(), depois strum() e, em seguida, checkTuning()
    • Imprima uma linha vazia
    • Para o piano: chame tune(), depois play() e, em seguida, checkTuning()

Observe como Guitar e Piano são instrumentos completamente diferentes, sem relação de herança, mas ambos ganham exatamente os mesmos métodos de afinação do mixin Tunable. Você escreve o código de afinação uma vez, e ambas as classes podem usá-lo com a palavra-chave with.

Saída esperada:

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

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

Folha de consulta

Um mixin é uma maneira de reutilizar código em várias classes não relacionadas sem usar herança. É um conjunto de métodos e propriedades que você pode "misturar" em qualquer classe.

Defina um mixin usando a palavra-chave mixin:

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

Aplique um mixin a uma classe usando a palavra-chave with:

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

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

Diferente de implements, você não precisa escrever a implementação do método por conta própria - o mixin fornece o código real, e sua classe ganha essa funcionalidade automaticamente.

Tanto Duck quanto Fish agora podem usar o método swim(), mesmo que não estejam relacionados por herança:

var duck = Duck();
duck.swim();  // Do mixin

var fish = Fish();
fish.swim();  // Mesma implementação, classe diferente

Experimente você mesmo

import 'instruments.dart';

void main() {
  // TODO: Criar um Guitar com a marca 'Fender'
  
  // TODO: Criar um Piano com 88 teclas
  
  // TODO: Para a guitarra: chamar tune(), depois strum(), depois checkTuning()
  
  // TODO: Imprimir uma linha vazia
  
  // TODO: Para o piano: chamar tune(), depois play(), depois checkTuning()
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos