Polimorfismo (POO)

Para um melhor entendimento deste Artigo veja o Índice (Programação Orientada a Objetos)
Iremos entrar agora em nosso último tópico sobre POO, e  muito interessante que é polimorfismo.Se você seguiu toda a trajetória do artigo sobre POO deve ter visto várias formas de polimorfismo (isso não foi um trocadilho) durante a leitura.

Vimos em:

Herança (POO)
Tipos Genéricos (Generics) (POO)
Abstração e Interface (POO)

Leia este artigo e depois do entendimento, volte a eles e tente identificar o uso do polimorfismo.

Aqui iremos abordar o polimorfismo de uma forma mais ampla e detalhada. Então vamos lá.

Polimorfismo

Etimologicamente, polimorfismo quer dizer:

1 Que se apresenta ou ocorre sob formas diversas.
2 Que assume ou passa por várias formas, fases etc.

Em orientação a objetos podemos dizer também que o objeto pode ter “vários comportamentos”.

Quando você chama um método ele pode se referir a qualquer objeto, por exemplo o método “Abrir()”, ele pode abrir uma tampa de garrafa, uma janela, uma porta, pode abrir alguma coisa.

Em polimorfismo é necessário que os métodos tenham a mesma assinatura, o mecanismo utilizado é o de redefinição de métodos (Overriding Definições – Intermediário (POO)) , não confundir com sobrecarga de métodos (Overload Definições – Intermediário (POO)).

Em polimorfismo podemos:

1 Instanciar objetos diferentes para um mesmo tipo.
2 Substituir condicionais com o polimorfismo.
3 Usar parâmetros que aceitam diferentes tipos de objetos desde que tenham a mesma herança de classes.

Vamos à alguns exemplos para reforçarmos as idéias.

Vamos criar nossas classes que servirão de base para todo o exemplo.

Iremos criar uma calculadora bem simples, que implemente as quatro operações básicas.

Classe Base

namespace Polimorfismo
{
    /// <summary>
    /// Classe base para efetuar os cálculos matemáticos
    /// </summary>
    abstract class CalculoMatematico
    {
        public virtual double Valor1 { get; set; }
        public virtual double Valor2 { get; set; }

        public abstract double Resultado();
    }
}

Multiplicação

namespace Polimorfismo
{
    class Multiplicacao : CalculoMatematico
    {
        public override double Resultado()
        {
            return Valor1 * Valor2;
        }
    }
}

Divisão

namespace Polimorfismo
{
    class Divisao : CalculoMatematico
    {
        public override double Resultado()
        {
            return Valor1 / Valor2;
        }
    }
}

Adição

namespace Polimorfismo
{
    class Adicao : CalculoMatematico
    {
        public override double Resultado()
        {
            return Valor1 + Valor2;
        }
    }
}

Subtração

namespace Polimorfismo
{
    class Subtracao : CalculoMatematico
    {
        public override double Resultado()
        {
            return Valor1 - Valor2;
        }
    }
}

Vamos agora ao primeiro exemplo.
Partindo de um mesmo tipo de objeto, podemos instanciar os outros tipos.
Mas para isso todos as classes devem implementar a mesma classe Pai.

namespace Polimorfismo
{
    class Program
    {
        static void Main(string[] args)
        {
            //veja que definimos o tipo
            //como CalculoMatematico
            CalculoMatematico calc;

            //aqui é criado como Adicao
            calc = new Adicao();
            calc.Valor1 = 23;
            calc.Valor2 = 34;
            Console.WriteLine(calc.Resultado().ToString("N2"));

            //aqui é criado como Divisao
            calc = new Divisao();
            calc.Valor1 = 23;
            calc.Valor2 = 34;
            Console.WriteLine(calc.Resultado().ToString("N2"));

            //aqui é criado como Subtracao
            calc = new Subtracao();
            calc.Valor1 = 23;
            calc.Valor2 = 34;
            Console.WriteLine(calc.Resultado().ToString("N2"));

            //aqui é criado como Multiplicacao
            calc = new Multiplicacao();
            calc.Valor1 = 23;
            calc.Valor2 = 34;
            Console.WriteLine(calc.Resultado().ToString("N2"));

            Console.ReadKey();
        }
    }
}

O nosso segundo item diz que podemos substituir condicionais com o uso de polimorfismo.
Será?
Vamos ver os exemplos abaixo, reparem bem na diferença entre os dois métodos da classe Calculadora

Definição da classe Calculadora:

namespace Polimorfismo
{
    public enum TipoCalculo
    {
        Adicao,
        Subtracao,
        Multiplicacao,
        Divisao
    }

    static class Calculadora
    {
        /// <summary>
        /// Neste método temos que informar o tipo
        /// de calculo que o mesmo irá fazer
        /// </summary>
        /// <param name="tipo">tipo do calculo feito</param>
        /// <param name="valor1">valor 1 para o calculo </param>
        /// <param name="valor2">valor 2 para o calculo</param>
        /// <returns>resultado da expressão</returns>
        public static double Calcular(TipoCalculo tipo, double valor1, double valor2)
        {
            double resultado = 0;

            //e aqui temos o condicional switch
            switch (tipo)
            {
                case TipoCalculo.Adicao:
                    resultado = valor1 + valor2;
                    break;
                case TipoCalculo.Subtracao:
                    resultado = valor1 - valor2;
                    break;
                case TipoCalculo.Multiplicacao:
                    resultado = valor1 * valor2;
                    break;
                case TipoCalculo.Divisao:
                    resultado = valor1 / valor2;
                    break;
                default:
                    throw new NotImplementedException("nunca poderá chegar aqui");
            }

            return resultado;
        }

        /// <summary>
        /// fazendo deste modo não precisamos
        /// utilizar nenhum condicional
        /// </summary>
        /// <param name="calc">tipo de calculo</param>
        /// <returns>resultado do calculo</returns>
        public static double Calcular(CalculoMatematico calc)
        {
            return calc.Resultado();
        }
    }
}

Exemplificando…

namespace Polimorfismo
{
    class Program
    {
        static void Main(string[] args)
        {
            //aqui vamos usar o condicional
            Console.WriteLine("Usando o Condicional");
            Console.WriteLine(Calculadora.Calcular(TipoCalculo.Adicao, 23, 34).ToString("N2"));
            Console.WriteLine(Calculadora.Calcular(TipoCalculo.Divisao, 23, 34).ToString("N2"));
            Console.WriteLine(Calculadora.Calcular(TipoCalculo.Multiplicacao, 23, 34).ToString("N2"));
            Console.WriteLine(Calculadora.Calcular(TipoCalculo.Subtracao, 23, 34).ToString("N2"));

            Console.WriteLine("".PadLeft(80, '-'));
            Console.WriteLine("Usando polimorfismo");
            //Aqui nao iremos usar o condicional.
            //substituiremos pelo uso do polimorfismo
            CalculoMatematico calc;

            //aqui é criado como Adicao
            calc = new Adicao();
            calc.Valor1 = 23;
            calc.Valor2 = 34;
            Console.WriteLine(Calculadora.Calcular(calc).ToString("N2"));

            //aqui é criado como Divisao
            calc = new Divisao();
            calc.Valor1 = 23;
            calc.Valor2 = 34;
            Console.WriteLine(Calculadora.Calcular(calc).ToString("N2"));

            //aqui é criado como Multiplicacao
            calc = new Multiplicacao();
            calc.Valor1 = 23;
            calc.Valor2 = 34;
            Console.WriteLine(Calculadora.Calcular(calc).ToString("N2"));

            //aqui é criado como Subtracao
            calc = new Subtracao();
            calc.Valor1 = 23;
            calc.Valor2 = 34;
            Console.WriteLine(Calculadora.Calcular(calc).ToString("N2"));

            Console.ReadKey();
        }
    }
}

Na classe Calculadora, além de exemplificarmos a substituição de um condicional com o uso do polimorfismo, ainda vimos a sobrecarga de métodos, temos dois métodos Calcular com assinaturas diferentes.

Para um melhor entendimento de sobrecarga recomendo a leitura do tópico Definições – Intermediário (POO).

E vimos também o item 3 que diz que podemos aceitar parâmetros de várias formas de objetos reparem que o método public static double Calcular(CalculoMatematico calc) aceitou os quatro tipos básicos.

Conclusão

Vimos o uso do polimorfismo em métodos, mas podemos usar a idéia em construtores, propriedades, no uso de Generics (Tipos Genéricos (Generics)), que podemos chamar de Polimorfismo Genérico.

Podemos citar rapidamente o uso de downcast (converter em uma classe mais específica) ,  upcast (definir em uma classe mais genérica).

namespace Polimorfismo
{
    class Program
    {
        static void Main(string[] args)
        {
            //definir objeto
            CalculoMatematico calc = new Adicao();
            calc.Valor1 = 22;
            calc.Valor2 = 33;

            //downcast (classe mais específica)
            Adicao adicao = (Adicao)calc;
            Console.WriteLine(adicao.Resultado());

            //upcast (classe mais genérica)
            calc = (CalculoMatematico)adicao;
            Console.WriteLine(calc.Resultado());

            Console.ReadKey();
        }
    }
}

Ver Índice

É isso ai pessoal 🙂
Até o próximo
♦ Marcelo

Marcelo

Nascido em Juruaia/MG em uma fazenda de criação de búfalos, e residindo na região Sul do Brasil.
Trabalha com desenvolvimento de aplicações desde os 17 anos. Atualmente é Arquiteto Organizacional na Unimake Software.
Para saber mais ... http://desenvolvedores.net/marcelo
[]'s

Você vai gostar de...

Postagens populares.

10 Comments

  1. Olá, boa noite!

    Eu acabei tendo uma pequena duvida, eu poderia usar o modificador virtual ao invez do abstract, nesse exemplo citado a cima?

    Uma vez que o modificador virtual tmb pode ser sobrescrito.

    1. Olá Lucas …

      Neste post http://techblog.desenvolvedores.net/2010/12/17/definicoes-basico-poo/ eu comento sobre isso. Se mesmo assim a dúvida permanecer, me avise.

      []´s

  2. Artigo muito bom, achei este blog através da indicação indireta do professor Ricardo da universidade XTI.

  3. ótima explicação
    também estou pesquisando por recomendação da Universidade XTI.

  4. Boa explicação, estou pesquisando o assunto por recomendação do Ricardo da Universidade XTI.
    Apesar do desse código aqui estra em C#, o conceito é o mesmo do que no java que é o que estamosvendo com o Ricardo da XTI.

    1. Obrigado Marcos.
      É bom ver um artigo que foi útil.
      O conceito nunca muda. E pode ser aplicado em linguagem de desenvolvimento que suporte OO.
      []’s

  5. Vindo do XTI também! Ótimas aulas e ótimo explicação 🙂

    1. Indicado por XTI tmbm, muito obrigado.

  6. Tbm achei bastante interessante a explicação, tbm estou acessando por recomendação do Ricardo da Universidade XTI!

  7. Bom, gostei da explicação, pediram para pesquisar sobre, como substituir expressões condicionais por polimorfismo. atraves do manolo do xti Ricardo.

Deixe um comentário

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.