Quando estamos desenvolvendo aplicações, é comum o uso de herança para evitar a reescrita de código. Basicamente, a herança é uma forma de uma classe obter atributos e métodos de outra classe, evitando a duplicidade e melhorando o reaproveitamento de código.
Porém, a herança por si só, não resolve todos os problemas. Imagine a seguinte situação:
Possuímos em nosso software, uma classe Pessoa
, com seus atributos e métodos e três classes que herdam de Pessoa
, as classes Funcionario
, Cliente
e Fornecedor
. Estas três classes são filhas de Pessoa e, por isso, herdam seus atributos e métodos:
Porém, imagine que queremos adicionar um método que é comum a diversas classes que herdam de Pessoa
, mas nem todas. A primeira opção seria desenvolver estes métodos apenas nas classes que iriam utilizá-las, porém, desta forma, há a duplicidade de código, já que mais de uma classe irá utilizar o mesmo método.
A segunda opção seria utilizar um recurso presente no Dart chamado de Mixins
, como veremos abaixo.
O que são Mixins e como eles funcionam?
Basicamente, os Mixins são recursos presentes no Dart que nos permitem adicionar um conjunto de “características” a uma classe sem a necessidade de utilizar uma herança.
Voltando ao exemplo anterior, imagine as classes abaixo:
abstract class Pessoa {
String _nome;
int _idade;
String _sexo;
String _email;
Pessoa(String nome, int idade, String sexo, String email) {
this._nome = nome;
this._idade = idade;
this._sexo = sexo;
this._email = email;
}
// getters e setters
// métodos
}
class Funcionario extends Pessoa {
String _cargo;
Funcionario(String nome, int idade, String sexo, String email, String cargo)
: this._cargo = cargo,
super(nome, idade, sexo, email);
// getters e setters
// métodos
}
class Cliente extends Pessoa {
bool _ativo;
Cliente(String nome, int idade, String sexo, String email, bool ativo)
: this._ativo = ativo,
super(nome, idade, sexo, email);
// getters e setters
// métodos
}
class Fornecedor extends Pessoa {
String _empresa;
Fornecedor(String nome, int idade, String sexo, String email, String empresa)
: this._empresa = empresa,
super(nome, idade, sexo, email);
// getters e setters
// métodos
}
Curso Dart - Fundamentos
Conhecer o cursoAgora precisamos implementar o método abastecer()
que servirá para um funcionário ou fornecedor abastecer a prateleira de um supermercado. Onde seria o melhor local para isso? Se implementarmos na classe Pessoa
, o Cliente
também conseguirá acesso a este método, o que não é correto para o que queremos. E é aí que entram os Mixins \o
Com o uso dos Mixins, podemos desenvolver o método abastecer()
de forma “isolada” e apenas permitir que determinadas classes possuam acesso a ele. Para isso, criamos o Mixin da seguinte forma:
mixin Abastecer {
void abastecer() {
print("Prateleira abstecida");
}
}
Por ser uma classe especial, os mixins
não precisam de construtores.
Agora, para definirmos as classes que poderão utilizar o método abastecer()
, utilizamos a palavra with
, como podemos ver abaixo:
class Funcionario extends Pessoa with Abastecer{
String _cargo;
Funcionario(String nome, int idade, String sexo, String email, String cargo)
: this._cargo = cargo,
super(nome, idade, sexo, email);
// getters e setters
// métodos
}
class Fornecedor extends Pessoa with Abastecer{
String _empresa;
Fornecedor(String nome, int idade, String sexo, String email, String empresa)
: this._empresa = empresa,
super(nome, idade, sexo, email);
// getters e setters
// métodos
}
Com isso, as classes Fornecedor
e Funcionario
poderão utilizar o método abastecer()
, sem que a classe Cliente
o faça:
main() {
cliente.abastecer(); //The method 'abastecer' isn't defined for the class 'Cliente'.
funcionario.abastecer(); //Prateleira abstecida
fornecedor.abastecer(); //Prateleira abstecida
}
Isso faz com que o reaproveitamento do nosso código seja ainda mais eficiente, já que o método abastecer()
só será implementado uma vez, mas poderá ser utilizado quantas vezes forem necessárias. Outras linguagens possuem recursos parecidos com os mixins no Dart, como o PHP e as Traits.