VB .NET - Programação Orientada a Objetos (em 10 lições práticas) - V
VB .NET é uma linguagem orientada a objetos. |
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 onde definimos uma classe base Conta e uma classe Poupanca que herda dessa classe base. 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 criar uma classe abstrata, uma classe que não pode ser instanciada diretamente e que você é obrigado a herdar para usar seus atributos e métodos e mostrar outros conceitos da programação OOP.
Os exemplos mostrados aqui foram construídos com base nos exemplos do livro : OOP with Microsoft Visual Basic .NET and Microsoft Visual C# Step by Step.
- Definindo uma classe base como uma classe abstrata - V |
Nesta aplicação você vai aprender a :
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 : http://www.microsoft.com/visualstudio/eng/2013-downloads
É 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 - Classe abstrata
Vamos pensar um pouco sobre o que fizemos até agora. Criamos uma classe base Conta a partir da qual criamos a classe derivada Poupanca. Temos assim duas classes concretas : a classe Conta e a classe Poupanca.
Se pensarmos em um banco do mundo real(lembre-se que classes devem modelar o mundo real) iremos constatar que na verdade não podemos abrir uma conta genérica. Muito provavelmente o banco irá nos oferecer um tipo de conta especifico para escolha. Em geral temos a conta corrente, a conta poupança, a conta especial,etc.
Dessa forma a nossa classe Conta deveria definir o comportamento comum de um conta genérica mesmo que nunca fossemos criar uma conta desse tipo.
Lembre que a classe Conta possui a propriedade ID cujo formato depende do tipo da conta o que não justifica implementar essa propriedade na classe Conta pois sua implementação é feita em cada classe derivada.
Outro fato importante é que a propriedade ID é uma propriedade essencial, pois identifica uma conta, deveria haver uma mecanismo que torna obrigatório a sua implementação em toda classe derivada da classe base.
Como a classe Conta é uma classe concreta ela pode ser instanciada (usando a palavra-chave new) e isso pode não ser muito indicado visto que existe a chance de se adicionar funcionalidades na classe base que não é apropriado às classes derivadas. Deveria haver uma maneira de não permitir que uma classe base seja instanciada sem perder o recurso da herança.
É exatamente isso que uma classe abstrata faz, ela permite o recurso da herança, permite que se defina métodos e propriedades que estejam apenas declarados e que sejam de implementação obrigatória e não pode ser instanciada.
Vamos então criar uma classe base Conta abstrata e nessa classe vamos definir apenas o comportamento comum a uma conta genérica implementando alguns métodos e deixando outros como métodos abstratos. Ao declarar um método como abstrato a classe se torna abstrata.
Resumo: Uma classe abstrata é uma classe que não pode ser instanciada. Você não pode criar um objeto a partir de uma classe abstrata. - Uma classe abstrata pode ser herdada e geralmente serve como classe base para outras classes. - Uma classe abstrata pode conter métodos abstratos e métodos comuns. Uma classe abstrata também podem possuir construtores, propriedades, indexadores e eventos. - Uma classe abstrata não pode ser estática (Shared). Uma classe abstrata não pode ser selada (NotInheritable). - Uma classe abstrata pode herdar de outra classe abstrata.
Métodos Abstratos: |
Construindo o projeto
Abra o Visual Studio 2012 Express for desktop e clique em New Project;
Selecione o template : Visual Basic -> Windows -> Windows Forms Application;
Informe o nome OOP e clique no botão OK:
seguir vamos incluir os seguintes controles no formulário form1.vb :
O leiaute do formulário é visto abaixo:
Criando a classe base abstrata, as propriedades e métodos abstratos e concretos
No menu PROJECT clique em Add Class;
Selecione o template Class e informe o nome Conta.vb e clique em Add;
Para definirmos uma classe abstrata no VB .NET temos que usar a palavra-chave MustInherit antes da palavra Class;
Vamos começar definindo a propriedades e os métodos abstratos na classe:
Veja como deve ficar a nossa classe Conta :
Public MustInherit Class Conta Public MustOverride ReadOnly Property ID() As String Public MustOverride Function ImprimirDeclaracao() As String End Class |
Note que temos apenas a declaração da propriedade e do método mas não a sua implementação. A implementação destes membros deverá ser feita pelas classes derivadas.
A declaração dos membros usa a palavra-chave MustOverride que indica que eles precisam ser definidos em cada classe derivada. A declaração de membros usando a palavra-chave MustOverride deve ser feita obrigatoriamente em uma classe abstrata usando a palavra-chave MustInherit. Uma classe abstrata pode conter membros abstratos e não abstratos ou concretos.(mas isso não é obrigatório)
A classe abstrata Conta deverá possuir os métodos Deposito e Saque e a propriedade Saldo definidos e implementados conforme abaixo:
PPublic MustInherit Class Conta Public MustOverride ReadOnly Property ID() As String Public MustOverride Function ImprimirDeclaracao() As String Public Function Deposito(ByVal valor As Decimal) As Decimal _saldo += valor _totalDepositos += valor Return _saldo End Function Public Overridable Function Saque(ByVal valor As Decimal) As Decimal _saldo -= valor _totalSaques += valor Return _saldo End Function Private _saldo As Decimal = 0D Public ReadOnly Property Saldo() As Decimal Get Return _saldo End Get End Property End Class |
Eu estou usando a sintaxe
anterior a versão 4.0 para que o código seja
compatível com as versões anteriores.
Para ver a nova sintaxe veja o meu
artigo sobre propriedades autoimplementadas: O método Saque esta definido como Overridable indicando que ela poderá ser sobrescrito na classe derivada. |
Vamos acrescentar duas novas propriedades na classe abstrata Conta para calcular o total de depósitos e saques de uma conta: TotalDepositos e TotalSaques cuja implementação esta definida conforme mostrada a seguir:
PPublic MustInherit Class Conta
Public MustOverride ReadOnly Property ID() As String
Public MustOverride Function ImprimirDeclaracao() As String
Public Function Deposito(ByVal valor As Decimal) As Decimal
_saldo += valor
_totalDepositos += valor
Return _saldo
End Function
Public Overridable Function Saque(ByVal valor As Decimal) As Decimal
_saldo -= valor
_totalSaques += valor
Return _saldo
End Function
Private _saldo As Decimal = 0D
Public ReadOnly Property Saldo() As Decimal
Get
Return _saldo
End Get
End Property
Private _totalDepositos As Decimal = 0D
Public ReadOnly Property TotalDepositos() As Decimal
Get
Return _totalDepositos
End Get
End Property
Private _totalSaques As Decimal = 0D
Public ReadOnly Property TotalSaques() As Decimal
Get
Return _totalSaques
End Get
End Property
End Class
|
Observe que os métodos
Saque
e Deposito mantém os campos _totalSaques
e _totalDepositos As propriedades TotalDepositos e TotalSaques são somente leitura. Ao sobrescrever o método Saque as classes derivadas não poderão acessar aos campos _totalSaques e _totalDepositos vistos que eles são campos definidos como Private. |
Criando a classe derivada Poupanca
Vamos agora criar a classe Poupanca derivada da classe Conta.
No menu PROJECT clique em Add Class;
Selecione o template Class e informe o nome Poupanca.vb e clique em Add;
A seguir inclua a declaração Inherits Conta para indicar que a classe Poupanca herda da classe Conta;
Como a classe Conta é uma classe base abstrata e possui a propriedade ID e o método ImprimirDeclaracao definidos como abstratos o Visual Studio irá criar automaticamente uma implementação vazia desses membros na classe derivada visto que eles são de implementação obrigatória em toda a classe derivada:
Vamos definir a implementação desses membros conforme mostra o código a seguir:
Public Class Poupanca Inherits Conta Public Overrides Function ImprimirDeclaracao() As String Dim declaracao As String = String.Format("{1}{0}" & _ "Saldo Inicial : R$0.00{0}Depositos: {2:C}{0}" & _ "Saques: {3:C}{0} Juros: {4:C}{0}" & _ "Saldo Final: {5:C}{0} ", _ New Object() {ControlChars.CrLf, Me.ID, _ Me.TotalDepositos - _totalJuros, _ Me.TotalSaques, Me._totalJuros, Me.Saldo}) Return declaracao End Function Public Overrides ReadOnly Property ID As String Get Return _titular + "-P" End Get End Property End Class |
Aqui mantivemos a mesma
definição para identifica uma conta de poupança. A conta será identifica pelo nome do titular seguido do sufixo "-P".
A plataforma .NET possuí um método para
formatar string chamado Format, na classe String.
Este método exige 2 parâmetros de entrada: Porém será gerada uma exception caso a formatação não for possível, por isso é necessário usar o método com cautela.
Sintaxe:
Ex:Teste = String.Format("Formatação
de string com {0} parâmetro. ", _ |
Note que tanto a propriedade como o método usam o modificador Overrides. Veja abaixo um lembrete de seu significado. (Lembre que o método da classe Pai deve usar Overridable)
A seguir vamos definir o construtor da classe derivada Poupanca como abaixo:
Private _titular As String Public Sub New(ByVal titular As String) _titular = titular End Sub |
A classe Poupanca deverá ser especializada pela definição da propriedade Juros() e do método AdicionarJuros() definidos como segue:
Private _juros As Decimal = 0.01D Public Property Juros() As Decimal Get Return _juros End Get Set(ByVal Value As Decimal) _juros = Value End Set End Property Private _totalJuros As Decimal = 0D Public Function AdicionarJuros() As Decimal Dim juros As Decimal = _juros * Me.Saldo _totalJuros += juros Me.Deposito(juros) Return Me.Saldo End Function |
Criando a classe derivada ContaCorrente
Vamos criar outra classe derivada da classe base Conta.
No menu PROJECT clique em Add Class;
Selecione o template Class e informe o nome ContaCorrente.vb e clique em Add;
A classe ContaCorrente deverá implementar a propriedade ID() identificando uma conta pelo nome do titular e o sufixo "-CC" e o método ImprimirDeclaração() conforme o código abaixo:
Public Class ContaCorrente Inherits Conta Public Overrides ReadOnly Property ID As String Get Return _titular + "-CC" End Get End Property Private _titular As String Public Sub New(ByVal titular As String) _titular = titular End Sub Public Overrides Function ImprimirDeclaracao() As String Dim declaracao As String = String.Format("{1}{0}" & _ "Saldo Inicial : R$0.00{0}Depositos: {2:C}{0} Saques: {3:C}{0} Saldo Final: {4:C}{0} ", _ New Object() {ControlChars.CrLf, Me.ID, Me.TotalDepositos, Me.TotalSaques, Me.Saldo}) Return declaracao End Function End Class |
Temos assim 3 classes em nosso projeto :
Não seria bom se pudéssemos usar uma ferramenta para descrever graficamente o relacionamento entre as classes ?
A UML - Unified Modeling Language é uma ferramenta gráfica que pode ser usada para descrever projetos orientado a objetos. Dessa forma a UML não é um método é uma linguagem de modelagem designada para especificar, visualizar, construir e documentar um sistema.
Ferramentas de desenvolvimento como a UML permitem que desenvolvedores possam discutir projetos usando um vocabulário comum. Tais ferramentas também diminuem a ambiguidade em uma especificação de um projeto de software.
Um dos recursos que a UML oferece para é o diagrama de classes que permitem ilustrar as classes, seus métodos propriedades.
A representação de uma classe usa um retângulo dividido em três partes:
|
Os diagrama se classes ilustram atributos e
operações de uma classe e as restrições como que os objetos
podem ser conectados ; descrevem também os tipos de objetos no
sistema e os relacionamentos entre estes objetos que podem ser :
associações
e abstrações.
Para poder representar a visibilidade dos atributos e operações em uma classe utiliza-se as seguintes marcas e significados:
Para mostrar o uso da UML vamos definir o diagrama de classe para a nossa classe Conta:
A UML reconhece três tipos mais importantes de relações: dependência, associação e generalização (ou herança).
Geralmente as classes não estão sós e se relacionam entre si. O relacionamento e a comunicação entre as classes definem responsabilidades , temos 3 tipos :
As representações usam a seguinte notação :
|
A representação UML para o relacionamento entre as 3 classes do nosso projeto é visto a seguir:
Testando as classes no projeto Windows Forms
Vamos agora testar a utilização das classes criadas no projeto em uma aplicação Windows Forms.
A nossa aplicação deverá exibir no formulário as contas existentes no primeiro combobox e o tipo de operação desejada no segundo.
O usuário poderá selecionar uma conta,uma operação e clicar no botão Executar para executar a operação ou no botão Imprimir para exibir as informações da conta selecionada.
Abra o formulário form1.vb e declare as variáveis contaPoupancaMacoratti e contaCorrenteMacoratti que são instâncias da classe Poupanca e ContaCorrente:
Dim
contaPoupancaMacoratti As New Poupanca("Macoratti")
Dim contaCorrenteMacoratti As New
ContaCorrente("Macoratti")
Vamos definir também uma variável contaSelecionada do tipo Conta:
Dim contaSelecionada As Conta
No evento Load do formulário vamos preencher o controle cobConta com as instâncias da classe Poupanca e ContaCorrente criadas anteriormente e atribuir o valor selecionado deste controle e do controle cboOperação para exibir o primeiro item; vamos preencher o TextBox - txtValor com o valor "50";
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Me.cboConta.Items.Add(contaPoupancaMacoratti) Me.cboConta.Items.Add(contaCorrenteMacoratti) Me.cboConta.SelectedIndex = 0 Me.cboOperacao.SelectedIndex = 0 Me.txtValor.Text = "50" End Sub |
No evento SelectedIndexChanged do combobox cboConta definimos o item selecionado como um objeto e convertemos o objeto para o tipo Conta atribuindo-o á variável contaSelecionada:
Private Sub cboConta_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboConta.SelectedIndexChanged Dim item As Object = Me.cboConta.SelectedItem contaSelecionada = CType(item, Conta) End Sub |
O evento Click do botão Imprimir chama a rotina ExibeDeclaracao:
Private Sub btnImprimir_Click(sender As Object, e As EventArgs) Handles btnImprimir.Click ExibeDeclaracao() End Sub |
A rotina ExibeDeclaracao() limpa o conteúdo do TextBox e chama o método ImprimirDeclaracao() da conta selecionada:
Private Sub ExibeDeclaracao() txtDeclaracao.Clear() txtDeclaracao.Text = contaSelecionada.ImprimirDeclaracao() End Sub |
No evento Click do botão Executar verificamos o tipo da operação selecionada: Saque ou Deposito e usando o objeto contaSelecionada executamos a operação na conta escolhida. Ao final chamamos a rotina ExibeDeclaracao():
Private Sub btnExecutar_Click(sender As Object, e As EventArgs) Handles btnExecutar.Click Dim valor As Decimal = 0D valor = Convert.ToDecimal(txtValor.Text) If cboOperacao.SelectedIndex = 0 Then contaSelecionada.Deposito(valor) ElseIf cboOperacao.SelectedIndex = 1 Then contaSelecionada.Saque(valor) End If ExibeDeclaracao() End Sub |
Abaixo vemos exemplos de execução para Poupanca e ContaCorrente:
Pegue o projeto completo aqui: ControleBancario.zip
Na próxima aula vou apresentar o conceito de interfaces e mostrar como podemos usar os seus recursos na linguagem VB .NET.
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
VB.NET - Orientação a objetos : Conceitos básicos em 10 lições
.NET Framework : introdução é classes mais ... - Macoratti.net
C# - Classes Abstratas, Interface e Polimorfismo - Macoratti.net