Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

Herança x Composição

Boa noite meus queridos,

Estou em uma luta constante com meu cérebro em relação Herança x Composição. Não foi somente no curso que vi que é indicado o uso da Composição ao invés da Herança, mas também em vários artigos na internet. O problema é, tenho os seguintes models: Empresa, Cliente, Fornecedor,

Com Herança seria fácil resolver, eu criaria uma classe Pessoa, depois outras duas classes PessoaFisica, PessoaJuridica e tudo certo, herdaria os atributos rua, cep etc... Porém, neste mesmo cenário, se eu quiser utilizar Composição? Eu crio a mesma classe Pessoa e somente instancia elas no construtor padrão de onde eu quero utilizar? e então já poderia inclusive delegar os getters e setters destes atributos através da composição?

Desde já agradeço,

Atenciosamente,

4 respostas

Fala Alan, beleza?

Cara achei um post interessante sobre Herança x Composição na DevMedia, clica aqui.

Nesse artigo ai tem uma boa explicação do porque usar a Composição ao invés da Herança e também uma implementação de exemplo.

Alan, pelo que entendi, seria isso mesmo que você disse. No construtor dessas duas classes seria instanciado um objeto do tipo Pessoa.

Exemplo da classe Pessoa, com apenas dois atributos:

public class Pessoa {

    private String rua;
    private String cep;

    public String getRua() {
        return this.rua;
    }
    public void setRua(String rua) {
        this.rua = rua;
    }
    public String getCep() {
        return this.cep;
    }
    public void setCep(String cep) {
        this.cep = cep;
    }

}

Como ficaria a classe PessoaFisica utilizando composição:

public class PessoaFisica {

    private Pessoa p;

    public PessoaFisica() {
        this.p = new Pessoa();
    }

    public String getRua() {
        return this.p.getRua();
    }

    public void setRua(String rua) {
        this.p.setRua(rua);
    }

    public String getCep() {
        return this.p.getCep();
    }

    public void setCep(String cep) {
        this.p.setCep(cep);
    }

}
solução!

Muito obrigado a todos pelo tempo dispersado em me ajudar. As ajudas foram de grande relevância e aproveito para deixar um outro artigo também que na minha opinião foi o mais esclarecer que encontrei: Clique aqui, Mais uma vez agradeço a ajuda de todos.

Bons estudos

Só cuidado com a nomenclatura "É UM", geralmente utilizada no caso de herança (como cita o artigo do DevMedia compartilhado aqui mais acima).

Não é seguro seguir essa regrinha do "É UM" pra definir se uma classe deve ou não herdar de outra.

Por exemplo:

class Retangulo {
  protected double altura;
  protected double largura;
}
class Quadrado extends Retangulo {
  // o que eu faço com os Setters de altura e largura?
  // embora um Quadrado seja um ("É UM") Retangulo, um
  // Retangulo PRECISA de ambos atributos altura e largura.
  // Já um Quadrado, ele SÓ PRECISA DE UMA MEDIDA, afinal
  // sua altura e largura DEVEM ser sempre idênticas
}

Talvez a solução que você pense seja: "isso é fácil de resolver! Basta fazer os Setters sempre setar ambos os atributos para o valor passado!"

void setAltura(double altura) {
  this.altura = altura;
  this.largura = altura;
}
void setLargura(double largura) {
  this.largura = largura;
  this.altura = largura;
}

Porém, se coloque no lugar do usuário de um Quadrado... ele deve imaginar que ao chamar o metodo setAltura() a largura também será alterada? É claro que não. Os métodos setAltura() e setLargura() estão fazendo mais do que o contrato da classe mãe (Retangulo) prometeu. Isso é uma quebra do princípio de substituição de Liskov...

Cuidado com essas "dicas" de orientação a objetos: "É UM", "TEM UM"... elas podem ser, na verdade, armadilhas.