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.
Desafio
FácilVamos 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
Tunablecom um métodotune()que imprimeTuning the instrument...e um métodocheckTuning()que imprimeTuning is perfect! - Uma classe
Guitarque usa o mixinTunable. Adicione uma propriedadeString brandcom um construtor. Inclua um métodostrum()que imprime[brand] guitar strumming chords - Uma classe
Pianoque também usa o mixinTunable. Adicione uma propriedadeint keyscom um construtor. Inclua um métodoplay()que imprimePlaying [keys]-key piano
- Um mixin
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
Guitarcom a marca'Fender' - Crie um
Pianocom88teclas - Para a guitarra: chame
tune(), depoisstrum()e, em seguida,checkTuning() - Imprima uma linha vazia
- Para o piano: chame
tune(), depoisplay()e, em seguida,checkTuning()
- Crie um
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 diferenteExperimente 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()
}
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
1Fundamentos de POO
Arquivos ExternosBibliotecas e ImportaçõesIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosVariáveis de InstânciaFundamentos de ConstrutoresRecapitulação - Calculadora Simples4Null Safety
Introdução ao Null SafetyNullable vs Non-NullableOs Operadores ? e !Palavra-chave Late e Null SafetyOperadores Null-AwareNull Safety em ClassesRecapitulação - Sistema de Perfil de Usuário7Classes Abstratas e Interfaces
Classes AbstratasMétodos AbstratosInterfaces em DartInterfaces ImplícitasImplementando vs EstendendoMúltiplas InterfacesRecapitulação - Calculadora de Formas10Coleções e Generics
Visão Geral de List, Set e MapColeções Type-SafeClasses GenéricasMétodos GenéricosRestrições de GenericsIterable e IteratorRecapitulação - Armazenamento Genérico13Conceitos Avançados de POO
Composição vs HerançaMétodos de ExtensãoClasses ChamáveisClasses Seladas (Dart 3)Records (Dart 3)Patterns & Matching (3.0)Enums com Métodos16Projeto: Gerenciamento de Biblioteca
Visão Geral do ProjetoClasses Livro e Usuário2Construtores em Dart
Construtor PadrãoConstrutores NomeadosListas de InicializaçãoConstrutores ConstantesConstrutores FactoryConstrutores de RedirecionamentoRecapitulação - Shape Builder5Encapsulamento
Membros Públicos vs PrivadosA Convenção do Prefixo _Privacidade em Nível de BibliotecaAprofundamento em Getters & SettersOcultação de InformaçãoRecapitulação - Registros de Estudantes8Mixins
Introdução aos MixinsCriando MixinsUsando Múltiplos MixinsPalavra-chave on em MixinsMixin vs HerançaMixin vs InterfaceRecapitulação - Sistema Animal11Métodos Especiais
Sobrescrita de toString()Sobrescrita de hashCode & ==Interface ComparableMétodo call()Sobrescrita de noSuchMethodRecapitulação - Coleção Personalizada14Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão ObserverPadrão Strategy3Propriedades de Classe
Membros de Instância vs EstáticosCampos Final & ConstVariáveis LateMétodos e Campos EstáticosGetters e SettersRecapitulação - Gerenciador de Conta Bancária6Herança
Herança BásicaA Palavra-chave superSobrescrita de MétodoA Anotação @overrideA Palavra-chave final para ClassesConstrutores e HerançaRecapitulação - Hierarquia de Funcionários9Polimorfismo
Fundamentos do PolimorfismoPolimorfismo via InterfacesVerificação de Tipos em Tempo de ExecuçãoOs Operadores is & asPalavra-chave CovariantRecapitulação - Processador de Pagamentos12POO Assíncrona
Futures e async/awaitFundamentos de StreamsStream ControllersConstrutores AssíncronosAsync em Métodos de ClasseRecapitulação - Data Fetcher15Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão Repository