Por que eu devo ler este artigo:Este tema é útil para os desenvolvedores que estão iniciando na Programação Orientada a Objetos, bem como para aqueles que desejam aprofundar-se na mesma. A orientação a objetos muita das vezes nos impõe certos desafios e não basta apenas conhecer a sua estrutura e conceitos para resolvê-los, é preciso dominá-los. O objetivo deste artigo é demonstrar algumas das principais vantagens e desvantagens da aplicação do paradigma de Orientação a Objetos e situações onde seu uso é fundamental para o desenvolvimento de aplicações mais flexíveis e fáceis de manter, bem como cenários onde a programação estruturada pode ainda ser a melhor opção.

Encontramos muitas definições sobre o que é Programação Orientada a Objetos (POO), que muitas das vezes estão cercadas de mitos e definições que distorcem o paradigma, e muitos desses mitos assombram os novatos que desejam aprendê-lo.

A intenção desse artigo é mostrar os principais erros e acertos durante o desenvolvimento orientado a objetos, esclarecendo as dúvidas mais frequentes a respeito da aplicação correta desse paradigma.

O que é, na verdade, Programação Orientada a Objetos? Como implementar? Quais as linguagens que suportam a mesma? Orientação a objetos é abstração do mundo real? Polimorfismo, mais herança, mais abstração é orientação a objetos? Desenvolver um sistema orientado a objetos é mais lento? Essas são algumas das várias perguntas feitas por diversos desenvolvedores, até os mais experientes no assunto. Vamos esclarecer essas questões com exemplos práticos, sempre procurando as melhores soluções.

A Programação Orientada a Objetos é um método de codificação que implica na utilização de objetos e suas relações a fim de descrever, de forma programática, o problema a ser resolvido. A definição clássica de POO foi baseada em três pilares fundamentais: encapsulamento, herança e polimorfismo.

O princípio do encapsulamento define que os elementos de dados não estão disponíveis para o mundo exterior diretamente. Em vez disso, seriam criados métodos para dar acesso a esses valores fora do objeto. Hoje em dia, linguagens como C#, por exemplo, têm a capacidade de utilizar não só métodos para essa função, mas também podemos criar propriedades que podem acessar elementos de dados internos do objeto, como mostra o código da Listagem 1.

Listagem 1. Exemplo de implementação do encapsulamento.


  public class Pessoa
  {
     private string _nome;

     public string Nome
     {
         get
         {
             return _nome;
         }
         set
         {
             _nome = value;
         }
     }
  }

O código apresentado é uma forma alternativa que a linguagem C# disponibiliza para acessar elementos que estão protegidos segundo o conceito de encapsulamento. Na linha 09 está sendo retornado conteúdo da variável interna _nome, mas ao invés de simplesmente retornar o valor, nós poderíamos efetuar várias manipulações dos dados antes de retornar o mesmo, assim como também antes de definir o valor para a variável interna _nome (linha 13) nós também poderíamos efetuar várias manipulações utilizando as propriedades.

Outro conceito fundamental que precisamos conhecer é o de herança, pois este recurso permite que os desenvolvedores possam definir os objetos de uma forma hierárquica, como mostra a Figura 1.

Diagrama de classe
Figura 1. Diagrama de classe.

O Diagrama de classe representa a base para criar um objeto ou um conjunto deles de forma abstrata para que possamos manipular informações do mundo real em nossos sistemas. Cada nível da hierarquia define um objeto mais específico do que o nível pai e cada nível herda todas as propriedades e métodos de seu objeto pai. Nesse ponto você define as propriedades e métodos mais específicos, fazendo assim com que os objetos que estão mais distantes sejam mais específicos.

Por fim, precisaremos também entender o funcionamento do terceiro pilar da POO que é o polimorfismo. Este pilar é a capacidade que os objetos de uma classe específica têm de ser tratados como objetos de uma classe base. As classes base podem definir e aplicar métodos virtuais e as classes derivadas podem substituí-los, o que significa que elas fornecem sua própria definição e implementação. Podemos então concluir que polimorfismo, como o próprio nome já diz, é a capacidade de um objeto de ter várias formas. Confira na Listagem 2 um exemplo de implementação do polimorfismo em C#.

Listagem 2. Implementação do polimorfismo.


   public abstract class Pessoa
   {
       public string Nome { get; set; }   
 
       public abstract decimal GetSaldoNoBanco();
 
   }

   public class PessoaFisica : Pessoa
   {
       public PessoaFisica()
       {
           Nome = "Pessoa Física";
       }

       public override decimal GetSaldoNoBanco()
       {
           return 1500;
       }
   }

   public class PessoaJuridica : Pessoa
   {
       public PessoaJuridica()
       {
           Nome = "Pessoa Jurídica";
       }
 
       public override decimal GetSaldoNoBanco()
       {
           return 20000;
       }
   }

   class Program
   {
       static void Main(string[] args)
       {
           var pessoaFisica = new PessoaFisica();
           var pessoaJuridica = new PessoaJuridica();

           ImprimirValorDoBanco(pessoaFisica);
           ImprimirValorDoBanco(pessoaJuridica);
 
           Console.Read();
       }

       private static void ImprimirValorDoBanco(Pessoa pessoa)
       {
           var valorBanco = pessoa.GetSaldoNoBanco();
           Console.WriteLine("Valor disponível na conta da {0} é: {1}",   
              pessoa.Nome, valorBanco);
       }
   }

Como podemos ver no código que implementa de fato os conceitos de polimorfismo, o método ImprimirValorDoBanco espera por parâmetro um objeto polimórfico do tipo Pessoa, ou seja, um objeto que em algum momento herda da classe Pesso ...

Quer ler esse conteúdo completo? Tenha acesso completo