Menu
Coddy logo textTech

Mixin vs Herança

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

Agora que você aprendeu como os mixins funcionam, vamos esclarecer quando usá-los em vez de herança. A principal diferença reside na relação que eles expressam.

Herança representa uma relação "é-um". Um Dog é um Animal. A subclasse é uma versão especializada da classe pai, e você só pode estender uma única classe.

Mixins, por outro lado, representam uma relação "pode-fazer". Um Dog pode nadar, mas nadar não é o que define um cachorro.

// Herança: Dog É um Animal
class Animal {
  String name;
  Animal(this.name);
}

class Dog extends Animal {
  Dog(String name) : super(name);
}

// Mixin: Dog PODE nadar (mas não é definido pelo ato de nadar)
mixin Swimming {
  void swim() => print('Swimming');
}

class Dog extends Animal with Swimming {
  Dog(String name) : super(name);
}

Use herança quando as classes compartilham uma identidade fundamental e você precisa de construtores na classe pai. Use mixins quando quiser adicionar funcionalidades a classes que não compartilham um ancestral comum.

RecursoHerançaMixin
Relacionamentoé-umpode-fazer
LimiteApenas um paiMúltiplos mixins
ConstrutoresPermitidoNão permitido
Caso de usoEspecializaçãoComportamento compartilhado

A melhor parte? Você pode combinar ambos - estender uma classe e incorporar múltiplas capacidades, dando às suas classes exatamente os recursos de que precisam.

challenge icon

Desafio

Fácil

Vamos construir um sistema de trabalhadores que demonstra quando usar herança versus mixins. Você criará uma classe base para o relacionamento "é um" (is-a) e mixins para as capacidades "pode fazer" (can-do), e então os combinará para mostrar como ambas as abordagens funcionam juntas.

Você organizará seu código em três arquivos:

  • worker.dart: Defina sua classe base que estabelece a identidade central de todos os trabalhadores:
    • Uma classe Worker com as propriedades String name e String department. Inclua um construtor que receba ambos os valores. Adicione um método introduce() que imprime '$name works in $department'
  • skills.dart: Defina mixins que representam capacidades que os trabalhadores podem ter (os relacionamentos "pode fazer"):
    • Um mixin CanCode com um método writeCode() que imprime 'Writing code...'
    • Um mixin CanDesign com um método createDesign() que imprime 'Creating design...'
    • Um mixin CanManage com um método leadTeam() que imprime 'Leading the team...'
  • main.dart: Importe ambos os arquivos e crie tipos de trabalhadores especializados que combinam herança com mixins:
    • Uma classe Developer que estende Worker e usa o mixin CanCode
    • Uma classe TechLead que estende Worker e usa os mixins CanCode e CanManage
    • Crie um Developer chamado 'Alice' no departamento 'Engineering'
    • Crie um TechLead chamado 'Bob' no departamento 'Engineering'
    • Para Alice: chame introduce() e depois writeCode()
    • Imprima uma linha vazia
    • Para Bob: chame introduce(), depois writeCode(), e então leadTeam()

Observe como tanto Developer quanto TechLead são trabalhadores (herança), mas eles podem fazer coisas diferentes (mixins). O TechLead combina múltiplas capacidades sem precisar de herança múltipla.

Saída esperada:

Alice works in Engineering
Writing code...

Bob works in Engineering
Writing code...
Leading the team...

Folha de consulta

A herança representa um relacionamento "é um" (uma subclasse é uma versão especializada do pai), enquanto os mixins representam um relacionamento "pode fazer" (adicionando capacidades sem definir uma identidade).

// Inheritance: Dog IS an Animal
class Animal {
  String name;
  Animal(this.name);
}

class Dog extends Animal {
  Dog(String name) : super(name);
}

// Mixin: Dog CAN swim
mixin Swimming {
  void swim() => print('Swimming');
}

class Dog extends Animal with Swimming {
  Dog(String name) : super(name);
}
RecursoHerançaMixin
Relacionamentoé umpode fazer
LimiteApenas um paiMúltiplos mixins
ConstrutoresPermitidoNão permitido
Caso de usoEspecializaçãoComportamento compartilhado

Você pode combinar ambas as abordagens - estender uma classe e misturar múltiplas capacidades:

class TechLead extends Worker with CanCode, CanManage {
  TechLead(String name, String department) : super(name, department);
}

Experimente você mesmo

import 'worker.dart';
import 'skills.dart';

// TODO: Crie uma classe Developer que estende Worker e usa o mixin CanCode

// TODO: Crie uma classe TechLead que estende Worker e usa ambos os mixins CanCode e CanManage

void main() {
  // TODO: Crie um Developer chamado 'Alice' no departamento 'Engineering'
  
  // TODO: Chame introduce() e depois writeCode() para Alice
  
  // TODO: Imprima uma linha vazia
  
  // TODO: Crie um TechLead chamado 'Bob' no departamento 'Engineering'
  
  // TODO: Chame introduce(), writeCode() e depois leadTeam() para Bob
}
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