Ainda não tem acesso? Estude com a gente! Matricule-se
Ainda não tem acesso? Estude com a gente! Matricule-se

Dúvida de Composição

Depois da aula sobre composição, entendi que atualmente usa-se mais composição e interface do que heranças.

Sendo assim, fui reescrever o código evitando ao máximo usar herança nos casos de pura reutilização, e ao final disso surgiu uma dúvida.

Após criar a classe "Pessoa" com os atributos (Agencia, Conta etc) e os getters & setters (getSaldo etc), utilizei o seguinte código no construtor de cada classe, como recomendado na aula para composições:

this.pessoaDesigner = new Pessoa();    

Após cada classe receber esse tipo de construtor (pessoaDiretor no Diretor, pessoaDesigner no Designer etc), notei que haveria um problema de duplicação de código, pois teríamos de reescrever as assinaturas de cada método nas classes.

Ou seja: precisaria de uma assinatura de getSaldo, de setSaldo e assim por diante no Gerente, no Diretor etc, fazendo referência a classe Pessoa, onde esses métodos realmente estão.

Ao invés disso, achei melhor colocar um getpessoa em cada classe, implementando tudo com uma linha de código ao invés de várias:

public class Designer {

    private Pessoa pessoaDesigner;

    public Designer() {
        this.pessoaDesigner = new Pessoa(); 

    }

    public Pessoa getpessoaDesigner(Designer d) {
        return this.pessoaDesigner;
    }

Desse jeito, fica possível chamar o objeto instanciado em cada construtor. Em um teste, é possível utilizar todos os métodos, mesmo sem herança:

    Designer d1 = new Designer();
    d1.getpessoaDesigner(d1).setSaldo(100);
    System.out.println(d1.getpessoaDesigner(d1).getSaldo());

Minhas dúvidas: 1) É possível enxugar esse código ainda mais, sem usar herança, com um código para getPessoa que não precisa ser escrito em cada classe (e sem a reescrita do método em cada classe)?

Pensei em colocar esse método na classe Pessoa (ou em outra classe separada) para ser instanciado no construtor, mas como o atributo de cada classe é privado, não sei como referenciar o "pessoaDesigner" da classe Designer (e os demais objetos do tipo Pessoa, presentes em cada classe - pessoaDiretor, pessoaGerente etc).

2) Seria possível criar uma interface comum a todos, e por polimorfismo utilizar o método da pergunta 1 - caso esse exista - para ter um getPessoa para todas as classes?

Ou seja, ao invés de um getpessoaDesigner, getpessoaGerente, getpessoaDiretor, um getPessoa que tenha como entrada uma interface "x", implementada pelo Gerente, Diretor etc.

3) Vale a pena tentar reduzir/eliminar a quantidade de heranças dessa forma? Qual a vantagem? E qual a desvantagem?

4) A chamada do código ficou muito maior - ao invés de "d1.setSaldo(100)", virou "d1.getpessoaDesigner(d1).setSaldo(100)".

Pensei, por exemplo, em criar uma espécie de atalho:

Designer d1 = new Designer();
Pessoa pd = d1.getpessoaDesigner(d1); 
pd.setSaldo(100);

Pensei em fazer algo assim para o método também. Enfim, qual seria a boa prática nesse caso?

É isso!

No geral, pensei em várias soluções usando herança, mas não consegui avançar usando apenas composição e interface, sem que exista uma certa repetição do código (exemplo: "getpessoa" em cada classe).

Obrigado

1 resposta

Olá Andre!

Vamos aos pontos citados:

Acredito que o código já está bem exuto. O getPessoa é necessário para esse tipo de implementação.

Porém , como você mesmo observou, dessa forma o código pode ganhar uma certa complexidade desnecessária que irá afetar na manutenção posterior. Seria melhor utilizar herança ou interfaces mesmo.

A composição é bastante útil quando temos atributos em uma classe que fazem sentido estar em outra.

Por exemplo:

public class Pessoa {
    String nome;
    String cpf;
    String pais;
    String rua;
    String bairro;
    int numero;    
}

Observe o seguinte: Quando estamos modelando orientado e objetos, queremos caracteristicas de um objeto. Uma pessoa tem nome, tem cpf, porém dizer que ela tem país, rua, bairro e numero de certa forma sooa meio estranho não acha? Não seria melhor dizermos que ela tem um Endereço?

Por isso criamos a classe e inserimos os atributos em comum dentro dela;

public class Endereco {
    String pais;
    String rua;
    String bairro;
    int numero;    
}

Assim conseguimos criar uma "abstração" melhor no nosso código - que além de mais legível se torna mais fácil de manusear:

public class Pessoa {
    String nome;
    String cpf;
    Endereco endereco;
}

A partir desse momento, uma pessoa tem um Endereço. Ela não é um Endereço. Esse é o ponto chave da diferença entre uma composição e uma herança.