VB .NET - Programação Orientada a Objetos (em 10 lições práticas) - IV
VB .NET é uma linguagem orientada a objetos. |
Na terceira parte do artigo apresentei a criação de sua primeira aplicação orientada a objetos onde aprendemos a criar classes, propriedades e métodos em uma aplicação Windows Forms. Vamos estender um pouco mais os nossos conhecimentos aprendendo a usar herança para criar classes especializadas.
Lição 10 - Juntando todas as partes - IV |
Embora VB .NET seja realmente uma linguagem orientada a objetos você pode usar a linguagem da mesma forma que usa uma linguagem estruturada como Visual Basic ou Pascal. Se você não incorporar os conceitos da orientação a objetos e aplicá-los em seus projetos construirá aplicações usando os mesmos conceitos das linguagens estruturadas. Isso não é de todo ruim mas você acaba não usando os recursos da linguagem e continua a construir projetos usando o paradigma procedural.
É como se você tivesse uma Ferrari mas se comportasse como se tivesse um fusca.
O segredo para incorporar os conceitos da orientação a objetos em suas aplicações e conhecer bem os conceitos e praticar. Então vamos lá...
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.
- Usando herança para criar classes especializadas |
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.
Conceitos Básicos - Herança
A herança é o método de programação usada para implementar a relação é-um (is-a) de um projeto orientado a objetos.
Dessa forma temos que um Botão é-um controle, um Cão é-um mamífero, uma conta de Poupança é-uma conta bancária, etc.
Nota: Você não deve confundir herança com composição que modela um relacionamento tem-um (has-a) entre um objeto e suas propriedades. Assim um Botão tem-um título, um Cão tem-um nome, uma conta de Poupança tem-um saldo, etc.
A herança permite criar classes a partir de classes existentes. Podemos criar novas classes a partir de uma classe base.
Neste caso podemos dizer que a classe derivada herda ou deriva da classe base. Outra terminologia comum usa superclasse para a classe base e subclasse para a classe derivada.
Definindo a classe base
Para a nossa aplicação de controle bancário pessoal vamos criar uma classe base chamada Conta.
Quando você pensa em uma conta bancária o que lhe vem a mente ?
O dono da conta(titular) , o saldo da conta, o número da conta (ID), os valores a débito(saques) e a crédito(depósitos), etc.
Dessa forma podemos identificar os seguintes membros:
Membro | Descrição |
Titular | Uma propriedade string que identifica o titular da conta |
ID | Uma propriedade string somente-leitura que identifica a conta |
Saldo | Uma propriedade decimal somente-leitura. O valor dessa propriedade depende dos depósitos e saques feitos na conta. |
Deposito | Método que usa um parâmetro : o valor depositado. Ele retorna o saldo após o deposito. |
Saque | Método que usa um parâmetro : o valor do saque. Ele retorna o saldo após o saque. |
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 ControleBancario e clique no botão OK:
A seguir vamos incluir os seguintes controles no formulário form1.vb :
O leiaute do formulário é visto abaixo:
Criando a classe base, as propriedades , métodos e o construtor da classe base
No menu PROJECT clique em Add Class;
Selecione o template Class e informe o nome Conta.vb e clique em Add;
1 - Definindo as propriedades e o construtor da classe base
Vamos iniciar definindo as propriedades ID e Saldo da conta e o construtor da classe. Essas propriedades são somente-leitura indicando que ela não podem ser alteradas somente lidas.
Abaixo temos o código definido na classe Conta :
Public Class Conta Private _titular As String Public ReadOnly Property ID() As String Get Return _titular End Get End Property Private _saldo As Decimal Public ReadOnly Property Saldo() As Decimal Get Return _saldo End Get End Property Public Sub New(ByVal titular As String) _titular = titular _saldo = 0D End Sub 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: |
2 - Definindo os métodos da classe base
Agora vamos definir os métodos Deposito e Saque da classe base usando a seguinte lógica:
Inclua na classe Conta o código para os métodos conforme abaixo:
Public Function Deposito(ByVal valor As Decimal) As Decimal _saldo += valor Return _saldo End Function Public Function Saque(ByVal valor As Decimal) As Decimal _saldo -= valor Return _saldo End Function |
Usando a classe Conta no projeto Windows Forms
Vamos agora testar a nossa classe Conta realizando saldos e depósitos e obtendo o saldo em nosso projeto Windows Forms.
A primeira coisa que temos que fazer e criar uma instância da classe Conta no início do formulário form1.vb:
Dim contaMacoratti As New Conta("Macoratti")
O código acima defina o objeto ContaMacoratti usando o construtor da classe Conta com o parâmetro "Macoratti" que é o nome do titular e passa a ser o ID da conta.
Após isso podemos exibir o saldo da conta ContaMacoratti. Então no evento Load do formulário vamos chamar a rotina atualizaSaldo() que exibe o saldo atualizado:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load atualizaSaldo() End Sub |
O código da rotina atualizaSaldo() é dado a seguir:
Private Sub atualizaSaldo() lblSaldo.Text = contaMacoratti.Saldo End Sub |
O código exibe o valor do saldo na label lblSaldo.Text. Como quando iniciarmos o projeto o construtor inicia o valor do saldo com zero o valor exibido será sempre zero no início do programa.
A seguir podemos definir o código do botão Depositar que irá realizar depósitos na conta no evento Click do botão de comando:
Private Sub btnDepositar_Click(sender As Object, e As EventArgs) Handles btnDepositar.Click Dim valor As Decimal = 0D If String.IsNullOrEmpty(txtValorDeposito.Text) Then MessageBox.Show("Informe um valor para depósito!") Else valor = Convert.ToDecimal(txtValorDeposito.Text) contaMacoratti.Deposito(valor) atualizaSaldo() End If End Sub |
Definimos a variável valor como Decimal e inicializamos o seu valor com zero (0D): Dim valor As Decimal = 0D
Verificamos se o valor informado no TextBox txtValorDeposito.Text pelo usuário é nulo ou vazio e avisamos o usuário: String.IsNullOrEmpty(txtValorDeposito.Text)
Quando o usuário informar um valor no TextBox iremos converter o valor informado para Decimal usando o método ToDecimal da classe Convert : valor = Convert.ToDecimal(txtValorDeposito.Text)
Chamamos o método Deposito da classe com o valor informado: contaMacoratti.Deposito(valor)
E chamamos a rotina para exibir o saldo atualizado : atualizaSaldo()
De forma a permitir somente valores válidos no TextBox txtValorDeposito.Text vamos usar o evento KeyPress e permitir somente valores numéricos , o ponto e a vírgula:
Private Sub txtValorDeposito_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles txtValorDeposito.KeyPress If Not Char.IsNumber(e.KeyChar) And Not e.KeyChar = vbBack And Not e.KeyChar = "." And Not e.KeyChar = "," Then e.Handled = True End If End Sub |
Neste momento já podemos executar a aplicação e realizar depósitos :
Fig 1.0 - Janela inicial do projeto | Fig 2.0 - Feito um depósito de 100 |
Na janela inicial teremos o saldo da conta exibido como valor zero e podemos digitar um valor e realizar um depósito.
Informando o valor 100 e clicando no botão Depositar teremos o saldo atualizado para 100.
Vamos agora definir o código do botão Sacar que deverá usar o método Saque da classe Conta e decrementar o saldo do valor informado. Abaixo vemos o código do evento Click do botão Sacar:
Private Sub btnSacar_Click(sender As Object, e As EventArgs) Handles btnSacar.Click
Dim valor As Decimal = 0D
If String.IsNullOrEmpty(txtValorSaque.Text) Then
MessageBox.Show("Informe um valor para Saque!")
Else
valor = Convert.ToDecimal(txtValorSaque.Text)
contaMacoratti.Saque(valor)
atualizaSaldo()
End If
End Sub
|
O código é idêntico ao do botão depositar. A única exceção é que chamamos o método Saque da classe conta com o valor informado: contaMacoratti.Saque(valor)
De forma a permitir somente valores válidos no TextBox txtValorSaque.Text vamos usar o evento KeyPress e permitir somente valores numéricos, o ponto e a vírgula:
Private Sub txtValorSaque_KeyPress(sender As Object, e As KeyPressEventArgs) Handles txtValorSaque.KeyPress
If Not Char.IsNumber(e.KeyChar) And Not e.KeyChar = vbBack And Not e.KeyChar = "." And Not e.KeyChar = "," Then
e.Handled = True
End If
End Sub
|
Após realizarmos dois depósitos no valor de R$ 100 e um saque no valor de R$ 50 teremos o resultado abaixo:
Se espiarmos a classe conta no Class View (Menu VIEW-> Class View) iremos obter:
Criando uma classe derivada da classe base
Vamos agora criar um nova classe chamada Poupanca que deverá ser uma classe derivada da nossa classe base Conta.
Quando você estende uma classe para criar uma nova classe , a nova classe estendida herda todas as propriedades e métodos da classe que foi estendida. A classe original é conhecida como superclasse , classe pai ou classe base ; a classe que estendida é conhecida como classe filha ou subclasse.(Se a classe filha não sobrepõe(overrides) nenhum procedimento da classe pai , ela herda todo o comportamento da classe pai.)
Algumas das características importantes sobre herança no VB.NET são:
A declaração Inherits implementa a herança no VB.NET
O VB.NET permite somente herança simples, ou seja , as classes derivadas podem ter somente uma única classe pai ou classe base.
Qualquer classe declarada por ser herdada. Para impedir que uma classe possa ser herdada você deve usar o modificar NoInheritable em sua declaração.
No VB.NET tudo são classes, e, todas as classes são herdadas de outras classes , sendo que todas elas derivam da classe-raiz simples chamada System.Object. Quando você declara uma classe sem especificar herança , ela herda implicitamente da classe System.Object
Uma classe pública (Public) não pode herdar uma classe privada (Private) ; uma classe amigável (Friend) não pode herdar uma classe (Private)
O VB.NET utiliza a palavra chave MyBase para se referir aos membros da classe base em uma classe derivada.
A classe Poupanca é idêntica a classe Conta exceto em relação aos seguintes aspectos:
Vamos criar a classe Poupança herdando da classe Conta para isso vamos usar a palavra-chave Inherits. No menu PROJECT clique em Add Class, selecione o template Class e informe o nome Poupanca.vb.
A seguir digite o código abaixo nesta classe:
Note que o compilador emite uma mensagem de erro:
Error
1 Class 'ControleBancario.Poupanca' must declare a 'Sub
New' because its base class 'ControleBancario.Conta' does not have an accessible 'Sub New' that can be called with no arguments. |
numa tradução livre: A classe 'ControleBancario.Poupanca' deve declarar um 'Sub New' pois classe base 'ControleBancario.Conta' não tem um Sub New acessível que pode ser chamado sem argumentos.
O erro indica que temos que declarar um construtor para a classe Poupanca pois o construtor da classe Conta não esta acessível.
Os construtores não são herdados, portanto, você deve adicioná-los na classe derivada. Além disso, sempre que um construtor é definido, ele inclui uma chamada implícita para o construtor sem parâmetros que pertence à classe base.
Na classe Conta, criamos somente um único construtor público que possui um parâmetro para o nome do titular da conta. Como o construtor sem parâmetros não existe na classe base, temos que fazer uma chamada explicita ao construtor. Logo temos que incluir esse construtor na classe Poupanca.
Vamos corrigir o erro digitando o código abaixo:
Este código introduz a palavra-chave MyBase.
MyBase refere-se à classe base da classe derivada. No caso do construtor, não há sentido em reescrever o código que você escreveu na classe base Conta. Uma chamada para a classe base é suficiente: MyBase.New()
Vamos agora pensar um pouco sobre as propriedades da classe Poupanca; iniciando pela propriedade ID que deverá identificar a conta de poupança.
Vamos identificar uma conta de poupança usando o nome do titular acrescentando o sufixo -P ao nome do titular da conta. Assim o titular da conta com o nome Macoratti será identificado na conta de poupança como Macoratti-P.
Para implementar isso na classe Poupanca teremos que modificar a propriedade ID que esta sendo herdada da classe Conta pela classe Poupanca sobrescrevendo o seu comportamento.
Para poder sobrescrever o seu comportamento usamos o modificador overrides na classe derivada conforme mostramos a seguir:
Observe que o compilador reporta um erro indicando que para podermos sobrescrever a propriedade ID na classe derivada temos que declará-la como Overridable na classe base. Então retorne a classe base Conta e altere o modificar da propriedade ID:
Public Overridable ReadOnly Property ID() As String Get Return _titular End Get End Property |
Agora podemos retornar à classe Poupanca e terminar a implementação da propriedade ID:
Agora temos outro erro. O compilador indica que o membro _titular da classe base não esta acessível.
Lembre que o membro _titular foi definido como Private e por isso esta visível somente na classe de origem. Para resolver esse erro temos que alterar o modificador do membro _titular de Private para Protected na classe Conta:
Protected _titular As String Public Overridable ReadOnly Property ID() As String Get Return _titular End Get End Property |
Com isso o erro será revolvido visto que modificador Protected torna a variável de uma classe base somente acessível as suas classes derivadas. O código final na classe Poupanca da propriedade ID ficou assim:
Public Overrides ReadOnly Property ID() As String Get Return Me._titular + "-P" End Get End Property |
Este código apresenta a palavras-chave Me que refere-se a instância de classe. Neste caso, utilizar Me não é obrigatório, poderíamos digitar apenas _titular.
Você pode usar a palavra-chave Me em situações em que você pode ter conflitos com nomes de variáveis.Talvez você tenha o mesmo campo declarado na classe e no método, neste caso a palavra-chave Me indica qual variável você deve usar.
Vamos agora definir a propriedade Juros na classe derivada Poupanca conforme o código abaixo:
Private _juros As Decimal = 0.01 Public Property Juros() As Decimal Get Return _juros End Get Set(ByVal Value As Decimal) _juros = Value End Set End Property |
Esta propriedade foi definida com um valor inicial :Private _juros As Decimal = 0.01
Agora crie o método AdicionarJuros na classe Poupanca conforme o código a seguir:
Public Function AdiconarJuros() As Decimal Me.Deposito(_juros * Me.Saldo) Return Me.Saldo End Function |
O código acima usa o método Deposito da classe base para incluir o valor do saldo atual acrescidos dos juros usando a propriedade Saldo.
Como campo _saldo foi definido como Private na classe base Conta e a propriedade Saldo é somente-leitura.Portanto, a única maneira de adicionar dinheiro na conta é, por definição, através do método Deposito.
Testando a classe Poupança no projeto Windows Forms
Para podermos testar a nova classe Poupanca que foi derivada da classe base Conta em nosso projeto Windows Forms vamos ter que ajustar o formulário para permitir que o usuário escolha depositar e sacar na conta ou na poupança e também permitir que o usuário defina uma taxa de juros e adicione o juros calculado na conta de poupança.
No início do formulário vamos criar uma instância da classe Poupanca:
Dim contaPoupancaMacoratti As New Poupanca("Macoratti")
Dessa forma poderemos usar o objeto contaPoupancaMacoratti com a respectiva conta de poupança criada com nome do titular - Macoratti.
Agora vamos ajustar o formulário. Abra o formulário form1.vb do projeto e inclua os seguintes controles a partir da Toolbox:
Disponha os controles conforme o leiaute da figura abaixo:
Vamos alterar o código dos botões Depositar e Sacar para que as operações sejam feitas na conta escolhida pelo usuário selecionando os controles radiobuttons. O código ajustado ficou assim:
Private Sub btnDepositar_Click(sender As Object, e As EventArgs) Handles btnDepositar.Click
Dim valor As Decimal = 0D
If String.IsNullOrEmpty(txtValorDeposito.Text) Then
MessageBox.Show("Informe um valor para depósito!")
Else
valor = Convert.ToDecimal(txtValorDeposito.Text)
If rdbDepositoConta.Checked Then
contaMacoratti.Deposito(valor)
ElseIf rdbDepositoPoupanca.Checked Then
contaPoupancaMacoratti.Deposito(valor)
End If
atualizaSaldo()
End If
End Sub
|
Private Sub btnSacar_Click(sender As Object, e As EventArgs) Handles btnSacar.Click
Dim valor As Decimal = 0D
If String.IsNullOrEmpty(txtValorSaque.Text) Then
MessageBox.Show("Informe um valor para Saque!")
Else
valor = Convert.ToDecimal(txtValorSaque.Text)
If rdbSaqueConta.Checked Then
contaMacoratti.Deposito(valor)
ElseIf rdbSaquePoupanca.Checked Then
contaPoupancaMacoratti.Deposito(valor)
End If
atualizaSaldo()
End If
End Sub
|
Temos que atualizar também a rotina atualizaSaldo de forma a exibir os valores para saldo da conta de poupança.
Private Sub atualizaSaldo()
lblSaldo.Text = contaMacoratti.Saldo.ToString("C")
lblSaldoPoupanca.Text = contaPoupancaMacoratti.Saldo.ToString("C")
End Sub
|
No código eu estou usando a instância da classe Poupanca - contaPoupancaMacoratti - e exibindo o saldo através da propriedade Saldo.
Note que estou formatando o resultado usando ToString("C") que formata a saída no formato da moeda local.(R$)
Finalmente vamos definir o código para adicionar os juros ao saldo da poupança usando o evento Click do botão - Adicionar Juros na Conta de Poupança:
Private Sub btnAdicionarJurosPoupanca_Click(sender As Object, e As EventArgs) Handles btnAdicionarJurosPoupanca.Click Dim taxaJuros As Decimal = 0D taxaJuros = Convert.ToDecimal(txtJurosPoupanca.Text) If taxaJuros <> 0 Then 'define o valor da taxa de juros na classe de poupança contaPoupancaMacoratti.Juros = taxaJuros End If 'inclui os juros na conta de poupança contaPoupancaMacoratti.AdicionarJuros() atualizaSaldo() End Sub |
Estamos convertendo o valor informado pelo usuário no TextBox -txtJurosPoupanca.
Se o valor informado for igual a zero estamos atualizando o valor da propriedade Juros. Caso contrário usaremos o valor padrão atribuído na propriedade.
Depois usamos o método AdicionarJuros() do objeto contaPoupancaMacoratti que é uma instância da classe Poupanca.
Executando o projeto e realizando um depósito e adicionando os juros na poupança teremos:
Para concluir esta parte vamos exibir também o nome do titular da conta e da poupança alterando a rotina atualizaSaldo:
Private Sub atualizaSaldo()
lblTitularConta.Text = contaMacoratti.ID
lblSaldo.Text = contaMacoratti.Saldo.ToString("C")
lblTitularPoupanca.Text = contaPoupancaMacoratti.ID
lblSaldoPoupanca.Text = contaPoupancaMacoratti.Saldo.ToString("C")
End Sub
|
Note que usamos a propriedade ID da classe base(contaMacoratti.ID) e da classe derivada (contaPoupancaMacoratti.ID) , que sobrescreveu o método da classe base:
Executando o projeto novamente e realizando algumas operações temos:
Pegue o projeto completo aqui: ControleBancario.zip
Na próxima aula irei mostrar os conceitos das classes abstratas e sua criação e testar a aplicação.
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