VB .NET - Programação Orientada a Objetos (em 10 lições práticas) - II


VB .NET é uma linguagem orientada a objetos.

Na primeira parte iniciamos os conceitos do paradigma da programação orientada a objetos e nesta segunda parte vamos continuar  a mostrar algumas das características da programação orientada a objetos (POO) presentes na linguagem Visual Basic .NET:

Lição 7 - Polimorfismo

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 veiculo 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. Quando sobrescrevemos(override) 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).

 

Imagine uma classe Veículo que define os comportamentos e atributos de qualquer veículo.

 

Uma característica básica de qualquer veículo é o movimento, logo nossa classe veículo pode expressar isso através de um método Mover().

 

Outra característica básica de qualquer veículo seria poder parar, afinal nenhum veículo fica eternamente em movimento, e isso seria expresso na classe veículo por um método Parar().

 

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

 

Vamos criar uma classe Veiculo , uma classe Automovel e uma classe Aeronave onde as duas últimas irão herdar da classe Veiculo e veremos como promover o polimorfismo usando o mecanismo da herança.

 

Vemos isso representado no diagrama abaixo:

Código das classes Veiculo, Automovel e Aeronave:

Public Class Veiculo

    Private m_tipo As String
    Public Property Tipo() As String

    Public Sub New(tipoVeiculo As String)
        Me.m_tipo = tipoVeiculo
        Console.WriteLine(tipoVeiculo)
    End Sub

    Public Overridable Sub Mover()
    End Sub

    Public Overridable Sub Parar()
    End Sub

End Class
Public Class Automovel
    Inherits Veiculo

    Public Sub New(tipoVeiculo As String)
        MyBase.New(tipoVeiculo)
    End Sub

    Public Overrides Sub Mover()
        Console.WriteLine("Acelerando o veículo")
    End Sub

    Public Overrides Sub Parar()
        Console.WriteLine("Estou brecando o veículo.")
    End Sub
End Class
Public Class Aeronave
    Inherits Veiculo

    Public Sub New(tipoVeiculo As String)
        MyBase.New(tipoVeiculo)
    End Sub

    Public Overrides Sub Mover()
        Console.WriteLine("Decolando a aeronave")
    End Sub

    Public Overrides Sub Parar()
        Console.WriteLine("Estou aterrisando a aeronave.")
    End Sub

End Class
Veiculo Automovel Aeronave

Na classe Veiculo temos:

  1. A propriedade pública Tipo que define o tipo de veículo
  2. O método virtual Mover() que define o comportamento Mover do veículo;
  3. O método virtual Parar() que define o comportamento Parar do veículo;
  4. O construtor da classe (Sub New) onde definimos o tipo de veículo;

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

Na classe Automovel temos:

  1. A classe Automovel herda da classe Veiculo;
  2. A classe Automovel sobrescreve os método Parar() e Mover() usando o modificador override;
  3. O construtor da classe Automovel executa o construtor da classe base (MyBase.New(tipoVeiculo);

Na classe Aeronave temos:

  1. A classe Aeronave herda da classe Veiculo;
  2. A classe Aeronave sobrescreve os método Parar() e Mover() usando o modificador override;
  3. O construtor da classe Aeronave executa o construtor da classe base;

Agora vamos definir o código para usar as classes e mostrar o comportamento de polimorfismo.

Module Module_OOP

    Sub Main()

        Dim veiculo As Veiculo() = New Veiculo(1) {}

        veiculo(0) = New Automovel("Ferrari")
        MovimentarVeiculo(veiculo(0))
        veiculo(1) = New Aeronave("Tucano")
        MovimentarVeiculo(veiculo(1))
        Console.ReadKey()

    End Sub

    Public Sub MovimentarVeiculo(veiculo As Veiculo)
        Console.WriteLine(veiculo.Tipo)
        veiculo.Mover()
    End Sub

End Module

No código cima temos :

- A criação de um vetor com dois elementos;
- A criação de duas instâncias, uma de Automovel e outra de Aeronave;
- A chamada do método MovimentarVeiculo que simula o movimento para cada veiculo;

Observe que no método MovimentarVeiculo estamos usando o método Mover() para cada tipo de veiculo que foi instanciado e cada objeto sabe realizar o movimento correto em resposta à mesma chamada do método.

Aqui estamos usando o conceito de polimorfismo pois o método Mover() é executado e a decisão de qual movimento será usado ocorre em tempo de execução;

Usamos veiculo.Mover() ao invés de Aeronave.Mover() ou Automovel.Mover().

Para usar o polimorfismo os objetos precisam executar as mesmas ações (métodos) mesmo que possuam comportamento diferente.

Lição 8 - Construtores e Destrutores

Um construtor é um método especial que é chamado automaticamente quando uma classe é instanciada. No VB.NET este método precisa ter o nome Sub New para identificar o construtor.

Public Class Aluno

    Dim idade As Integer
    Public Property Email As String
    Public Property Nome As String

    Public Sub New(ByVal _nome As String, ByVal _email As String)
        Nome = _nome
        Email = _email
    End Sub

    Public Sub New()
        idade = 18
        Console.WriteLine("Criando um Aluno com idade igual a 18")
    End Sub

End Class

Esta classe possui dois construtores:

  1. Sub New() - O construtor padrão
  2. Sub New(ByVal _nome As String, ByVal _email As String) - O construtor que inicializa as propriedades;

Sempre que você criar um objeto Aluno um nome padrão será atribuído automaticamente pelo construtor.

Quando um objeto é criado, seus membros,  podem ser inicializados por um método construtor.

Um construtor é um método que recebe o nome especial New().

O construtor é invocado automaticamente toda vez que um objeto dessa classe é instanciado.

Quando um objeto de uma classe é criado, inicializadores podem ser fornecidos entre parênteses á direita do nome New.

Uma classe pode conter construtores sobrecarregados para fornecer uma variedade de maneiras de inicializar os objetos desta classe.

Se nenhum construtor é definido para uma classe , é criado um construtor padrão que não aceita argumentos.

E se você não criar nenhum construtor (você não é obrigado a fazer isto.) a sua classe terá o chamado construtor padrão que não requer nenhum argumento e nada faz. A partir do momento que você criar o seu construtor o construtor padrão não será mais gerado.

Um Destrutor é um método especial que é chamado automaticamente quando uma classe é destruída no VB .NET.

Lição 9 - Propriedades

Você pode usar tanto as propriedades e os campos para armazenar informações em um objeto. Enquanto os campos são simplesmente variáveis públicas, as propriedades usam procedimentos de propriedade para controlar como os valores que são definidos ou retornados. Você pode usar as palavras-chave Get/Set obter/definir as propriedades.

Com isto concluímos que propriedades são variáveis especiais que permitem encapsular o código da minha classe.

Geralmente as propriedades possuem os procedimentos Get e Set mas podemos usar os modificadores :

ReadOnly - permite somente a leitura da propriedade - Só possui Get

    Public ReadOnly Property nomeCachorro() As String
        Get
            Return nome
        End Get
    End Property

WriteOnly - permite somente a atribuição de valor a propriedade - Só possui Set

     Public Property corCachorro() As String
        Set(ByVal Value As String)
            cor = Value
        End Set
    End Property

Você pode também incluir um código de validação na propriedade e permitir a alteração somente com base em alguns critérios. Por exemplo podemos criar a propriedade alturaCachorro que define o valor da altura de um cachorro e permitir que ela seja alterada somente para valores menores que 10. Veja como fica o código :

    Public Property alturaCachorro() As Integer
        Get
            Return altura
        End Get
        Set(ByVal Value As Integer)
            If altura < 10 Then
                altura = Value
            End If
        End Set
    End Property

A partir do VS 2010 temos um novo recurso chamado propriedades autoimplementadas.

Property Nome As String = "Macoratti"

Property PedidosLista As New List(Of Pedidos)

Aqui temos o que chamamos de propriedades autoimplementadas que torna a declaração de propriedades mais concisa quando nenhuma lógica adicional é requerida na propriedade.

Outros exemplos para o VB .NET:

Public Property Nome As String
Public Property Items As New List(Of String) From {"M", "T", "W"}
Public Property ID As New Guid()

Uma propriedade autoimplementada é equivalente a uma propriedade para o qual o valor da propriedade é armazenado em um campo privado. Assim economizamos linhas de código.

Lição 10 - Juntando todas as partes

Vamos repassar os conceitos aprendidos de forma resumida para tornar mais claro o entendimento:

Característica Conceito
Macoratti é um homem (um objeto). objetos
A data de nascimento de Macoratti é 11 de Setembro de 1978, sexo: masculino, olhos: castanhos. propriedades
Macoratti pode comer, dormir, beber, sonhar, falar e pensar. métodos
Macoratti é uma instância da classe Programador. classe
Macoratti é baseado em outro objeto chamado Programador. protótipo
Macoratti trata dados (como a data de nascimento) e métodos que trabalham com essa data(como o cálculo da idade) encapsulamento
Não sabemos como o método para calcular a idade funciona internamente. O objeto pode ter dados privados como número de dias de cada mês, mas não sabemos. Ocultamento de informação
Macoratti faz parte de um objeto Equipe e junto com Jefferson, um Arquiteto de Software, e com Jessica, uma Web Designer, eles trabalham no mesmo projeto. agregação, composição
Web Designer, Arquiteto de Software e Programador são todos baseados e estendem o objeto Pessoa. Herança
Podemos chamar o mesmo método Falar para o objeto Macoratti, para o objeto Jefferson e para o objeto Jessica e eles irão produzir resultados diferentes:
  • Macoratti (como Programador) irá falar sobre código e desempenho;
  • Jefferson (como Arquiteto) irá falar de estrutura de projeto boas práticas;
  • Jessica (como Web Designer) irá falar sobre interfaces;

Cada objeto herda o método Falar da classe Pessoa e irão customizar o método.

Polimorfismo

Na  próxima aula irei mostrar como podemos criar uma aplicação usando a linguagem VB .NET aplicando os conceitos da orientação a objetos.

Referências:


José Carlos Macoratti