.NET

29 ago, 2014

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

Publicidade

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 criar métodos e propriedades na classe base e como especializar essa classe criando classes derivadas. Vimos assim como usar os recursos da herança, sobrescrever um método e como interagir como controles de formulários em uma aplicação Windows Forms.

Neste artigo, vamos aplicar o conceito de polimorfismo e mostrar como podemos usar os seus recursos em nossa aplicação bancária.

Polimorfismo – conceitos e utilização – Parte  08

Nesta aplicação você vai aprender a definir e utilizar polimorfismo.

Objetivo: Criar uma pequena aplicação para controlar os saques, depósitos e saldos de uma conta pessoal usando os conceitos programação orientada a objetos na linguagem VB .NET.

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 sendo 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ê deseja controlar sua conta bancária pessoal registrando os saques, depósitos e controlando o saldo da conta usando os conceitos da programação orientada a objetos da linguagem VB .NET.

Conceitos Básicos – Polimorfismo II

Polimorfismo significa muitas formas. Na orientação a objetos você pode enviar uma mesma mensagem para diferentes objetos e fazê-los responder da maneira correta. Você pode enviar a mensagem ‘mover’ para cada objeto semelhante a um veículo e cada um vai se comportar de maneira diferente para atender a sua solicitação.

Quando uma mesma mensagem pode ser processada de diferentes formas, temos um exemplo de polimorfismo.

Uma definição mais formal diria: “Polimorfismo é o princípio pelo qual duas ou mais classes derivadas de uma mesma superclasse podem invocar métodos que têm a mesma identificação (assinatura), mas comportamentos distintos, especializados para cada classe derivada, usando para tanto uma referência a um objeto do tipo da superclasse”.

Usando polimorfismo podemos:

  1. Invocar métodos da classe derivada através da classe base em tempo de execução;
  2. Permitir que classes forneçam diferentes implementações de métodos que são chamados com o mesmo nome.

Existem dois tipos básicos de polimorfismo:

  1. Polimorfismo em tempo de compilação (Overloading/Sobrecarga);
  2. Polimorfismo em tempo de execução (Overriding/Sobrescrita).

O polimorfismo em tempo de compilação utiliza a sobrecarga de métodos e operadores sendo também chamado de ligação precoce (early binding). A utilização da sobrecarga de métodos realiza a tarefa com distintos parâmetros de entrada.

O polimorfismo em tempo de execução pode ser feito usando herança e métodos virtuais (Overridable). Quando sobrescrevemos(Overrides) os métodos virtuais estamos alterando o comportamento dos métodos para a classe derivada. Isto também é conhecido como ligação tardia (late binding).

Nesta aula veremos a utilização de polimorfismo usando a sobrecarga de métodos.

Apresentação do cenário

Para tornar o exemplo mais simples e fácil de entender, eu não vou criar um projeto Windows Forms, como fiz na aula anterior. Vou criar um projeto do tipo Console Application.

Pegando ‘carona’ no exemplo da classe Conta, vamos aumentar a abstração do exemplo e aplicar os conceitos de polimorfismo.

Imagine uma classe Conta que define os comportamentos e atributos de qualquer Conta. Vamos supor que uma característica básica de qualquer conta seja o comportamento ‘retirar dinheiro’, logo, nossa classe Conta pode expressar isso através de um método Sacar().

Outra característica básica de qualquer conta seria o comportamento ‘depositar dinheiro’, afinal uma conta deve ter um valor monetário e isso seria expresso na classeConta por um método Depositar().

Vamos definir um atributo para identificar o tipo da conta que será expresso pela propriedade Tipo.

Então, podemos criar uma classe Conta contendo esses métodos e atributo e usar o mecanismo da herança para que outras classes herdem os atributos e comportamentos comuns.

Tudo bem. Até aqui não temos nada de novo, foi isso o que fizemos. Vamos, então, criar uma classe Conta , uma classe ContaPoupanca e uma classe ContaInvestimento, onde as duas últimas irão herdar da classe Conta e veremos como promover o polimorfismo usando o mecanismo da herança com sobrecarga de métodos.

Abaixo vemos a representação da herança usando um diagrama UML simplificado:

vbn_oop84

Criando o projeto e implementando o polimorfismo usando sobrecarga de métodos

Abra o Visual Studio 2012 Express for desktop e clique em New Project. Selecione o template: Visual Basic -> Windows -> Console Application. Informe o nome OOP_Polimorfismo2 e clique no botão OK. No menu PROJECT, clique em Add Class e depois selecione o template Class e informe o nome Conta.vb e clique em Add.

vbn_oop81

A seguir, vamos definir as propriedades Tipo e Saldo, um construtor padrão que define o tipo da conta, os métodos Sacar() e Depositar(), conforme o código a seguir:

Nota: Neste exemplo eu estou usando a nova sintaxe das propriedades autoimplementadas para a linguagem VB.NET.

Public Class Conta
    Public Property TipoConta As String
    Public Property Saldo As Decimal
    public Property TipoCliente as String
    public Property DataAbertura as Date

   Public Sub New(tipoConta As String, _tipoCliente as String, _dataAbertura as Date)
        Me.TipoConta = tipoConta
        Me.TipoCliente = _tipoCliente
        Me.DataAbertura = _dataAbertura  
        Me.Saldo = 0
       Console.WriteLine("Tipo de Conta : " + TipoConta + ", Cliente = " + TipoCliente + ", Data Abertura =  " + DataAbertura.ToString + " , Saldo = " + Saldo.ToString())
   End Sub

    Public Overridable Sub Sacar(valor As Decimal)
        Saldo -= valor
    End Sub

    Public Overridable Sub Depositar(valor As Decimal)
        Saldo += valor
    End Sub

End Class

Até aqui nada de novo. Vamos, então, definir dois métodos que realizam o cálculo do valor da manutenção da conta, sendo que um deles irá realizar o calculo usando as informações sobre o tipo do cliente e a data de abertura e o outro método irá realizar o cálculo com base no tipo de cliente, data em que foi aberta e tipo da conta.

Teremos então dois métodos com o mesmo nome, pois eles fazem a mesma coisa : calcular o valor da manutenção da conta.

Mas os métodos irão possuir assinaturas diferentes, pois um método usa as informações ‘tipo de cliente’ e ‘data de abertura’ e o outro usa além desses, o ‘tipo da conta’.

 Public Sub calculaValorTarifaManutencao(_tipoConta As String, _dataAbertura As Date)
        Console.WriteLine("Tarifa da conta : TipoConta e DataAbertura")
    End Sub
    Public Sub calculaValorTarifaManutencao(_tipoConta As String, _dataAbertura As Date, TipoCliente As String)
        Console.WriteLine("Tarifa da conta : TipoConta, DataAbertura e TipoCliente")
    End Sub

Nota: Eu sei que poderíamos ter criado um único método para realizar o cálculo da manutenção da conta usando as três informações, mas fiz assim para mostrar a sobrecarga de métodos, que é um conceito onde usamos o mesmo nome do método muitas vezes na mesma classe, mas cada método com número de parâmetros diferentes. Com base nos parâmetros passados, a execução é decidida em tempo de compilação.

Vamos agora criar a classe ContaPoupanca.

No menu PROJECT clique em Add Class. Selecione o template Class e informe o nome ContaPoupanca.vb e clique em Add. A seguir, inclua o código abaixo para a classe ContaPoupanca, que herda da classe conta. A palavra Inherits indica a herança entre as classes:

Public Class ContaPoupanca
    Inherits Conta
    Public Sub New(_tipoConta As String, _tipoCliente As String, _dataAbertura As Date)
        MyBase.New(_tipoConta, _tipoCliente, _dataAbertura)
    End Sub
    Public Overrides Sub Sacar(valor As Decimal)
        Console.WriteLine("Sacando da conta de poupança " + valor.ToString)
    End Sub
    Public Overrides Sub Depositar(valor As Decimal)
        Console.WriteLine("Depositando na conta de poupanca." + valor.ToString)
    End Sub
End Class

Note que o método construtor da classe ContaPoupanca chama o construtor da classe base usando a palavra-chave MyBase.New() e que os métodos Sacar() e Depositar() possuem o modificar Overrides que indica que esses métodos estão sendo sobrescritos na classe derivada.

Vamos agora criar a classe ContaInvestimento.

No menu PROJECT clique em Add Class. Selecione o template Class e informe o nome ContaInvestimento.vb e clique em Add. A seguir, inclua o código abaixo para essa classe que herda da classe conta:

Public Class ContaInvestimento
    Inherits Conta
    Public Sub New(_tipoConta As String, _tipoCliente As String, _dataAbertura As Date)
        MyBase.New(_tipoConta, _tipoCliente, _dataAbertura)
    End Sub
    Public Overrides Sub Sacar(valor As Decimal)
        Console.WriteLine("Sacando da conta de investimento " + valor.ToString)
    End Sub
    Public Overrides Sub Depositar(valor As Decimal)
        Console.WriteLine("Depositando na conta de investimento." + valor.ToString)
    End Sub
End Class

Nota: Eu não implementei nenhum código mais complexo nos métodos Sacar(), Depositar() e  calculaValorTarifaManutencao() para tornar o exemplo mais simples.

Na classe Conta temos:

  1. A propriedade pública TipoConta que define o tipo da conta;(Poupanca,Corrente,Investimento etc);
  2. A propriedade pública TipoCliente que define o tipo de cliente.( Especial, Comum etc);
  3. A propriedade pública DataAbertura que define a data de abertura da conta;
  4. A propriedade pública Saldo que define o saldo da conta;
  5. O método virtual Sacar() que define o comportamento de retirar dinheiro da conta;
  6. O método virtual Depositar() que define o comportamento de por dinheiro na conta;
  7. O método  calculaValorTarifaManutencao(_tipoConta As String, _dataAbertura As Date);
  8. O método  calculaValorTarifaManutencao(_tipoConta As String, _dataAbertura As Date, TipoCliente As String);
  9. O construtor da classe onde definimos o tipo da conta, tipo de cliente e data de abertura da conta;(Sub New).

O modificador de acesso Overridable indica que o método pode ser sobrescrito na classe derivada.

Na classe ContaPoupanca temos:

  1. A classe ContaPoupanca herda da classe Conta; (Inherits);
  2. A classe ContaPoupanca sobrescreve os método Sacar() e Depositar() usando o modificador Overrides;
  3. O construtor da classe ContaPoupanca executa o construtor da classe base; (MyBase.New()).

Na classe ContaInvestimento temos:

  1. A classe ContaInvestimento herda da classe Conta;(Inherits);
  2. A classe ContaInvestimento sobrescreve os método Sacar() e Depositar() usando o modificador Overrides;
  3. O construtor da classe ContaInvestimento executa o construtor da classe base;(MyBase.New()).

Agora vamos definir o código para usar as classes e mostrar o comportamento de polimorfismo. Inclua o código abaixo no Modulo Module1 usando a rotina Main():

Module Module1
    Sub Main()
        Dim poupanca As New ContaPoupanca("Poupanca", "Especial", Now.Date)
        Dim investimento As New ContaInvestimento("Investimento", "Comum", Convert.ToDateTime("05/07/2012"))
          poupanca.Depositar(100)
          investimento.Sacar(200)
        poupanca.calculaValorTarifaManutencao(poupanca.TipoConta, poupanca.DataAbertura, poupanca.TipoCliente)
        investimento.calculaValorTarifaManutencao(investimento.TipoConta, investimento.DataAbertura)
       Console.ReadKey()
    End Sub
End Module

vbn_oop83

No código cima temos:

  • A criação de duas instâncias, uma de ContaPoupanca e outra de ContaInvestimento;
  • A chamada do método Depositar que simula o comportamento de por dinheiro na conta de poupança;
  • A chamada do método Sacar que simula o comportamento de retirar dinheiro na conta de investimento;

A seguir usamos o método calculaValorTarifaManutencao() tanto para a conta de poupança como para conta de investimento e em tempo de compilação o recursoIntelissense nos mostra os parâmetros que podemos usar para usar o método desejado da classe base.

vbn_oop82

Aqui estamos usando o conceito de polimorfismo, pois o método calcula ValorTarifaManutencao() é executado e a decisão de qual comportamento será usado ocorre em tempo de compilação.

Então, a sobrecarga de métodos pode ser considerada um tipo de polimorfismo estático (essa afirmação não é uma unanimidade e você pode encontrar textos afirmando o contrário. Tudo vai depender qual o enfoque você dá na definição de polimorfismo).

Na verdade, podemos acrescentar que tanto a sobrescrita como a sobrecarga são na verdade usadas para implementar o polimorfismo.

Na próxima aula vamos recordar herança e composição e mostrar qual é melhor usar em determinado cenário.

Pegue o projeto completo aqui: OOP_Polimorfismo2.zip