Herança x Composição
Por Izabela Vanessa de Almeida Melo
(izabela.vmelo@gmail.com)
Você provavelmente já ouviu falar e/ou já usou a Programação Orientada a Objetos. Mas você lembra quais são as diferenças, vantagens e desvantagens entre Herança e Composição, dois conceitos que são bastante importantes nesse contexto?

A Programação Orientada a Objetos (POO) tem o objetivo de tentar aproximar ao máximo o mundo virtual do mundo real. Nesse contexto, o programador é o responsável por construir o mundo dos objetos, determinando a forma de interação entre eles. Um objeto "conversa" com outro por meio de mensagens e, de acordo com essas, executa alguma ação. Tudo isso é moldado pelo programador OO.

Dois conceitos que todo programador OO deve ter conhecimento e saber distinguir são Herança e Composição. Ambos facilitam o reuso. Mas, quais são as peculiaridades de cada um?

Na herança, as características comuns a um grupo de classes são reunidas em uma superclasse ("classe mãe") e, a partir dessa, outras classes podem ser especificadas. Cada subclasse ("classe filha") apresenta as características (métodos, atributos, ...) especificadas pela superclasse e, além disso, pode especificar o que for definido como sua particularidade. A seguir (Figura 1), temos um exemplo simples: uma superclasse Animal e suas subclasses Mamífero, Ave, Cachorro, Homem, Beija-Flor. Note que a herança não se restringe apenas a um nível. A subclasse Cachorro, além de apresentar as características da superclasse Mamífero, também apresenta, além das suas particularidades, as características da superclasse de sua "mãe", Animal. Note que, de acordo com os objetivos da POO, tal organização acontece no mundo real (um cachorro é um mamífero que, por sua vez, é um animal).

Figura 1 - Exemplo de Herança.

Outro exemplo clássico (Figura 2) de herança é uma superclasse Pessoa com suas subclasses PessoaFisica e PessoaJuridica. A subclasse PessoaFisica possui os dois atributos de sua superclasse (nome e endereço) e possui o seu atributo particular CPF. O mesmo acontece com a subclasse PessoaJuridica, porém sua particularidade é o CNPJ.

Figura 2 - Outro exemplo de Herança [2].

Na composição, estendemos uma classe e delegamos o trabalho para o objeto dessa classe. Para facilitar, quando temos um sentido de que uma classe TEM UMA outra classe, usa-se composição (diferentemente de herança que tem o sentido de "É UM"). Imagine o exemplo de uma classe Empresa que tem um Endereço (Figura 3). Pode-se deixar a classe Empresa responsável pela classe Endereço (composição).

Figura 3 - Exemplo de composição [1].

A herança tem a vantagem de capturar o que é comum e o isolar daquilo que é diferente, além de ser vista diretamente no código OO. Porém, ela gera um forte acoplamento, pois uma pequena mudança numa superclasse afeta todas as suas subclasses. Essa característica da herança viola um dos princípios da Orientação a Objetos que é manter o fraco acoplamento. Além disso, a herança é um relacionamento estático. Algumas vezes, os objetos do mundo OO precisam sofrer mutações, e algumas delas não são possíveis quando utilizamos herança (por exemplo, se um funcionário mudou de cargo dentro de uma empresa, seu objeto deveria mudar de classe, o que não ocorre).

Considere o exemplo a seguir (Figura 4). Nele, por usar herança, se um Agente for viajar, ele será um Passageiro, mas, com tal disposição das classes, realizar a mudança de classe do objeto se torna uma tarefa complicada.

Figura 4 - Exemplo de um problema na herança [1].

Agora, observe o mesmo exemplo da Figura 4 usando composição (Figura 5). Note que ficou muito mais fácil permitir que uma Pessoa possua vários papéis. Usando composição, nós estendemos a funcionalidade de Pessoa, sem usar herança. Com esse mecanismo, o comportamento de um objeto pode ser definido em tempo de execução (não ficando preso ao tempo de compilação).

Figura 5 - Mesmo exemplo da Figura 4 usando, agora, composição [1].

Com isso, é possível perceber que existem várias diferenças entre Herança e Composição. Enquanto aquela é mais fácil de entender, permite um maior reuso de código e isola o comportamento comum do comportamento diferenciado, esta permite um maior dinamismo dos objetos do programa, permitindo que objetos tenham comportamentos diferentes ao longo de sua vida. Mas, como nem tudo são flores, cada uma tem suas desvantagens. A herança permite um forte acoplamento (o que viola os princípios OO). Já a composição, apesar de todas as suas vantagens já descritas nesta matéria, dificulta o entendimento por parte dos programadores, uma vez que é um código dinâmico e parametrizado.

Dessa forma, cabe ao programador OO avaliar, de acordo com os requisitos de seu projeto, se é melhor utilizar herança ou composição.


Fontes:

[1] http://www.dsc.ufcg.edu.br/~jacques/cursos/map/html/pat/herancavscomposicao.htm. Último acesso em 20/06/2011.

[2] http://www.macoratti.net/11/05/oop_cph1.htm. Último acesso em 20/06/2011.