Dev (Back & Front)ARTIGO

Programação Orientada a Objetos em 10 lições práticas – Parte 09

Neste artigo, vamos comparar herança com composição, analisar seus fundamentos e saber decidir quando usar os recursos.

Até o momento, apresentamos os conceitos da programação orientada a objetos afetos à linguagem VB .NET, usando uma aplicação bem simples de controle de saldos bancários, na qual definimos uma classe base Conta e uma classe Poupanca que herda dessa classe base (Inherits). Vimos como aplicar o conceito de polimorfismo e mostramos como podemos usar os seus recursos em nossa aplicação bancária.

Neste artigo, vamos comparar herança com composição, analisar seus fundamentos e saber decidir quando usar os recursos.

Aqui você vai aprender a identificar herança e composição e saber qual utilizar, qual é mais indicada.

Objetivo: Apresentar os conceitos de herança e composição, mostrando seus recursos e comparando-os para saber decidir qual usar em determinada situação.

Recursos usados: Visual Studio 2012 Express for Windows desktop

Nota: Neste momento, já se encontra disponível a versão 2013.

É importante salientar que a ferramenta usada é gratuita, não possui restrições e é totalmente funcional. Ao fazer o download da ferramenta, você também pode baixar o pacote de idioma para localizar o produto para a língua portuguesa.

Problema: Você precisa aprender herança e composição, conhecer seus recursos e saber qual utilizar em determinado cenário.

Conceitos básicos – Herança

O paradigma da Orientação a objetos – OO – traz muitos conceitos novos e, para quem vem do paradigma procedural usando as linguagens estruturadas e do desenvolvimento orientado ao banco de dados, às vezes muitos desses conceitos podem não ser bem compreendidos.

O termo Programação procedural (ou programação procedimental) é às vezes utilizado como sinônimo de Programação imperativa (Paradigma de programação que especifica os passos que um programa deve seguir para alcançar um estado desejado), mas o termo pode se referir a um paradigma de programação baseado no conceito de chamadas a procedimento. Procedimentos, também conhecidos como rotinas, sub-rotinas, métodos, ou funções (que não devem ser confundidas com funções matemáticas, mas são similares àquelas usadas na programação funcional) simplesmente contêm um conjunto de passos computacionais a serem executados. Um dado procedimento pode ser chamado a qualquer hora durante a execução de um programa, inclusive por outros procedimentos ou por si mesmo.
Fonte: Wikipedia

Apenas para ilustrar, abaixo temos uma tabela comparando as características básicas do paradigma OO e do procedural:

Programação Orientada a Objetos Programação Estruturada
Métodos Procedimentos e funções
Instâncias de variáveis Variáveis
Mensagens Chamadas a procedimentos e funções
Classes Tipos de dados definidos pelo usuário
Herança
Polimorfismo

Se você quer construir um código limpo, legível, escalável e reutilizável usando os conceitos da OO, precisará ter uma compreensão sólida dos principais conceitos desse paradigma.

Como o C# e VB .NET são linguagens Orientada a Objetos(OO), podemos usá-las para criar projetos dentro do paradigma OO.

Este artigo procura focar dois mecanismos básicos usados para reutilizar código muito utilizados na programação orientada a objetos (POO): a herança e a composição.

Qual seria melhor? Usar composição ou usar herança?

Uma rápida revisão dos conceitos

1 – Herança

  • Estende atributos e métodos de uma classe;
  • Classe Pai, classe Base ou Superclasse é a classe que foi herdada;
  • Classe Filha ou Sub Classe é a classe que herda da classe Pai;
  • Generalização – Obtém similaridades entre classes e define novas classes. As classes mais genéricas são as classes Pai;
  • Especialização – Identifica atributos e métodos não correspondentes entre classes distintas colocando-os na classe filha;
  • É um.

Exemplo:

vb-1

– Pessoa – classe Pai, classe Base ou Super Classe

  • PessoaFisica – classe Filha ou sub classe
  • PessoaJuridica – classe Filha ou sub classe

– A classe Pessoa é a classe genérica;

– As classes PessoaJuridica e PessoaFisica são especializações;

– PessoaFisica É uma pessoa;

– PessoaJuridica É uma pessoa.

Implementação VB .NET:

Namespace Herança

Public Class Pessoa
     Private nome As String
     Private Endereco As String      
End Class

Public Class PessoaFisica
         Inherits Pessoa

    Private CPF As String
    Public Sub New()
    End Sub
End Class

Public Class PessoaJuridica
      Inherits Pessoa

     Private CNPJ As String
     Public Sub New()
     End Sub
End Class

End Namespace

2 – Composição

  • Estende uma classe e delega o trabalho para o objeto dessa classe;
  • Uma instância da classe existente é usada como componente da outra classe;
  • Tem um.

Exemplo:

vb-2
– Pedido – Classe que contém uma instância da classe Itens;

– Um pedido TEM UM Item.

Implementação VB .NET:

Public Class Pedido
	Private i As Itens
	Public Sub New()          
    		i = New Itens()
	End Sub
End Class

Public Class Itens
	Public Sub New()
	End Sub
End Class

Resposta: Herança ou Composição

Em geral, usar composição traz mais vantagens do que utilizar herança.

Os projetos tendem a ser mais simples e reutilizáveis em se favorecendo a composição em vez da herança.

Na verdade, a herança deve ser usada com cuidado e apenas em algumas situações.

Estranhou a resposta???

Você achava que herança era o suprassumo dos recursos do arsenal das linguagens Orientadas a Objeto??

Se você pensava assim, estava enganado…

Então senta que o leão é manso…

Obs: Lembrando que nem a linguagem C# nem a VB .NET suportam herança múltipla; assim, uma classe pode herdar de apenas uma única classe.

Ah!! Outro detalhe: estou considerando apenas herança de implementação, e não estou entrando em detalhes em herança de Interface. Ok?

Mas por que devemos mesmos dar preferência à composição e não a herança?

Usando herança:

  1. Ao usar herança, estamos violando um dos pilares da orientação a objeto: o encapsulamento, visto que os detalhes da implementação da classe Pai são expostos nas classes Filhas;
  2. Ao usar herança, estamos violando um dos princípios básicos das boas práticas de programação: manter o acoplamento entre as classes fracas, visto que as classes filhas estão fortemente acopladas à classe Pai e alterar uma classe Pai pode afetar todas as classes Filhas;
  3. As implementações herdadas da classe Pai pelas classes Filhas não podem ser alteradas em tempo de execução.

Usando composição:

  1. Os objetos que foram instanciados e estão contidos na classe que os instanciou são acessados somente através de sua interface;
  2. A composição pode ser definida dinamicamente em tempo de execução pela obtenção de referência de objetos a objetos do mesmo tipo;
  3. A composição apresenta uma menor dependência de implementações;
  4. Na composição, temos cada classe focada em apenas uma tarefa (princípio SRP); – veja o artigo SRP – O princípio da responsabilidade únican;
  5. Na composição, temos um bom encapsulamento, visto que os detalhes internos dos objetos instanciados não são visíveis.

Percebemos que a herança viola dois conceitos básicos que sempre devemos aplicar em nosso código, enquanto que a composição naturalmente nos leva a usar tais conceitos.

Mas então eu nunca devo usar herança??? (Nunca é uma palavra que nós mortais deveríamos pronunciar com muito cuidado….)

Não existe um mandamento para nunca usar herança, mas podemos definir algumas regras para identificar quando podemos usá-la de forma a não ter os problemas que ela acarreta:

Então , considere a utilização da herança se:

  • A classe Filha expressar “um tipo especial de” e não “ser um papel desempenhado por”;
  • Uma instância de uma classe Filha NUNCA precisar se tornar um objeto de outra classe;
  • A classe filha estender em vez de substituir total ou parcialmente as responsabilidades da classe Pai;
  • A sua hierarquia de herança representar um relacionamento “É um” e não um relacionamento “Tem um”;
  • Você desejar ou precisar realizar alterações globais para as suas classes filhas alterando uma classe Pai;
  • Você precisar aplicar a mesma classe e métodos a diferente tipos de dados;
  • Você puder comparar seu objeto A com outro B dizendo, que A “É UM tipo de…” B;
  • Você estiver construindo uma família de tipos (relacionados entre si).

Obs: Cuidado com a aplicação do princípio “É Um”; às vezes, ele nos leva a cometer erros que percebemos só depois de olharmos o código. (Vide a violação do princípio LSP ) – veja o artigo : O princípio de substituição de Liskok (LSP).

Agora concluindo: herança e composição não são mutuamente exclusivas. Podemos usar as técnicas em conjunto para otimizar os resultados.

Lembre-se da regra máxima: Programe para uma interface, e não para uma implementação.

No último artigo desta série, vamos apresentar o padrão IoC – Inversão de Controle.

é referência em Visual Basic no Brasil e autor dos livros "Aprenda Rápido: ASP" e "ASP, ADO e Banco de Dados na Internet". Mantenedor do site macoratti.net.

Ver perfil