Enviar um café pro programador

Pode me ajudar a transformar cafeína em código?

Herança ou Composição: Qual o melhor?

Acabamos de estudar a Herança, que assim como a Composição, é uma forma de tratar a relação entre os objetos, como eles devem ser vistos e trabalhados.

Talvez agora, como iniciante em nossa apostila de Java, isso não seja motivo de muita preocupação para você, mas certamente no futuro será. E para melhor esclarecer isso, nossa apostila de Java irá falar mais sobre as vantagens e desvantagens de cada uma dessas técnicas.


Herança ou Composição? Qual usar?

Quando estudamos os conceitos de Herança pela primeira vez, parece ser um pouco confuso.
Com um pouco mais de dedicação, começamos a entender e ver que as coisas fazem sentido.
E quando vemos exemplos de aplicações reais, como os exemplos e exercícios mostrados por nós, é que vamos o quão interessante é a Herança.

E não é pra menos, pois podemos herdar variáveis, métodos e muitas linhas de código apenas escrevendo uma palavra: extends.
Sem dúvida, é uma ideia fantástica e um dos recursos mais utilizados, que fazem com que o paradigma de orientação à objetos seja muitíssimo usado.

Porém, se notar bem, fornecemos duas maneiras de se trabalhar com objetos de classe diferentes, através da Composição e através da Herança. Então naturalmente surge a dúvida? Qual usar?
Qual a melhor de se trabalhar?

A resposta, como a maioria das coisas em programação (e em computação, de um modo geral), é a mesma:
depende. Depende dos seus objetivos, depende da situação.
Nenhuma é inútil, melhor ou pior.

E temos sorte de ter duas boas opções para usar em nossos projetos, algumas linguagens só oferecem uma maneira de resolver as coisas.




Herança: vantagens e desvantagens


Já que já mostramos, tanto para Composição como para Herança, seu uso e benefícios, vamos falar de alguns problemas.
Basicamente, as coisas vão girar em torno do acoplamento.

Na sua experiência de vida, o que seria um acoplamento?
Duas peças de carro bem acopladas?
Seriam duas peças totalmente encaixadas e unidas, que praticamente não dá pra desgrudar e funcionam, para aquele propósito, perfeitamente, mas para outros, não.
Afinal, dá muito trabalho usar para outros fins coisas que são bem acopladas.

Herança é isso.
Quando uma classe herda outra, ela está MUITO ligada à ela. Ela está altamente acoplada, interligada, dependente.
Se a classe super muda, ela muda. É um processo estático.
Fez isso? Tá feito, não muda mais, só programando e compilando tudo de novo.

E qual a parte ruim disso? Nem sempre queremos as coisas tão acopladas.
Talvez você queira trabalhar com objeto mais simples, como o "Opala", que é derivado da classe "Carro".
Porém, nessa classe "Carro" você criou diversas variáveis e métodos que não vão existir na classe "Opala", como GPS embutido e injeção eletrônica.

Ou seja, as vezes você herda coisas que não precisa. E para usar essa classe, teria que ter toda a hierarquia acima dela.
Há também problemas de segurança, da preocupação de proteger certos métodos e variáveis.
Pense bem ao estender uma classe: preciso mesmo repassar esse método? E essa variável?
Talvez você coloque uma variável como protected e outra como private, para proteger.
Mas percebe que tinha usado em outra classe esses dados, como se fossem public.

Notou? Pra uns é private, pra outros é public, uns podem acessar, outros não, as vezes depende.
A medida que o projeto cresce, esse acoplamento entre classes pode se tornar complexo.
É ruim? Em alguns casos sim, em outros a Herança pode ser perfeita.

Composição: vantagens e desvantagens



A composição é o contrário, no quesito acoplamento.
Apenas passamos um objeto para outro (ou usamos uma classe em outra).
É uma troca de informações. Uma não depende da outra para existir, não herda nada.

Ou seja, as classes e objetos em uma Composition estão mais livres, mais soltos. Assim é bem mais fácil reutilizar código em uma Composição

São como as peças de um relógio ou de um computador. Funcionam todas juntas, elas se encaixam como um quebra-cabeça.
Mas nada te impede de tirar uma peça e colocar outra.
Ou inventar uma nova peça para acoplar ali. As coisas não são muito estáticas e imutáveis.

Outra vantagem é que quando passamos um objeto, quem o controla pode-se utilizar de apenas um ou outro método ou dado, sem se dar conta do resto.
Não precisa passar todas as informações. Diferente da herança, onde uma classe filha ao herdar, recebe muita coisa da classe mãe. Algumas dessas coisas nem sempre devem ser repassadas.

E a desvantagem? Bom, no caso da herança, como mostramos, as vezes economizamos MUITO trabalho herdando métodos e variáveis.
As vezes simplesmente colocamos um extends, alteramos um ou outro método, mexemos em duas ou três linhas e temos as coisas funcionando.

Delegando na Composição

Quando enviamos um Objeto/Classe para outro, este deverá saber EXATAMENTE o que deve fazer.

Por isso, em composição, é bem comum o conceito de delegação, que é quando você envia informações para objeto(s)/classe(s), onde cada um irá fazer uma coisa diferente e específica.

É como se você fosse o chefe, e vai pedir para o programador começar a desenvolver o aplicativo de um projeto, para o design fazer a arte e para o webmaster criar o site do projeto.
Você está delegando a cada um deles uma tarefa.

Eles vão receber este objeto, o projeto, e irão fazer as alterações nele.
Irão checar dados deste objeto, se já foi criado isso, aquilo, se já foi alterado, se é realmente para fazer esta mudança ou não.

O contrário também ocorre: quando um objeto vai ser enviado, ele pode ir na classe que o vai receber e checar alguns dados e informações.
Esta 'consulta' de dados é chamada de callback.

Quando criamos o Jogo da Velha em Java, criamos uma classe chamada "Jogo", que vai receber dois "Jogadores" e o "Tabuleiro". É uma composição, pois essa classe Jogo recebe os objetos dos jogadores bem como um tabuleiro, e vai 'mandando' nas coisas.
É como se fosse um gerente, um chefe: olha se o tabuleiro tá vazio, se alguém ganhou, quantas jogadas fez cada jogador, checa se este já decidiu a linha e coluna que vai jogar, se a casa que ele jogou está mesmo vazia etc etc.
Resumindo: criamos a classe "Jogo" com uma série de métodos que irão fazer as coisas funcionarem, onde delegamos uma função à cada um deles, de modo que, quando todos trabalham juntos, o jogo funciona.

Onde estudar mais sobre Herança e Composição

E o assunto rende, cada caso é um caso, e é sempre bom ler mais sobre o assunto e experiências de outros programadores.
Por isso vamos deixas dois ótimos links para vocês se aprofundarem no assunto:

Blog da Caelum - Como não aprender Orientação a Objetos - Herança
Macoratti - OOP: Herança x Composição

Nenhum comentário:

Contribuir com o Java Progressivo

Que tal apoiar e fazer crescer o ensino da programação no Brasil ?

Ajudar nosso país a crescer e se desenvolver cada vez mais, tecnologicamente?

Clica abaixo pra saber mais!

Apoiar o Projeto Progressivo


Tutoriais de Java