VB .NET - Programação Orientada a Objetos (em 10 lições práticas) - VI
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 definir uma interface e mostrar como podemos usar os seus recursos em nossa aplicação bancária.
- Definindo e usando uma Interface - VI |
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 - Interfaces
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.
Criamos então uma classe base Conta abstrata e nessa classe definimos apenas o comportamento comum a uma conta genérica implementando alguns métodos e deixando outros como métodos abstratos.
Outra alternativa seria criar uma interface ao invés de uma classe abstrata.
Mas o que vem a ser uma interface ?
Uma interface, no paradigma da orientação a objetos, é um tipo de classe que contém apenas as assinaturas de métodos, propriedades, eventos e indexadores.
A implementação dos membros é feita por uma classe concreta ou estrutura (struct) que implementa os métodos da interface.
Uma interface nunca pode ser instanciada e contém somente as assinaturas dos métodos, não possuindo construtores nem campos, sendo que seus membros são sempre públicos e não podem ser declarados como estáticos (static) nem como overridable, ou seja, os métodos não podem ser sobrepostos e sim devem ser implementados.
Uma interface é parecida com uma classe abstrata; a diferença é que uma classe abstrata pode possuir métodos que não estejam implementados e pode possuir métodos que estejam implementados.
Como o VB.NET não suporta herança múltipla as interfaces permitem que uma classe estenda múltiplas interfaces contornando o problema (se é que isto é um problema ). Para implementar uma interface o VB.NET usamos o modificador - Implements .
As interfaces são declaradas usando a palavra-chave - Interface. Geralmente o nome dado a uma interface começa com a letra I. Podemos ter duas sintaxes para o uso com interfaces:
Interface IForma
End Interface
Class Linha
Implements IForma
End Class
|
Interface IForma
End Interface
Class Linha: Implements IForma
End Class
|
Podemos então para o nosso exemplo criar uma interface ao invés de uma classe abstrata como fizemos na aula anterior. Podemos criar uma interface para Conta contendo 3 métodos : Depositar(), Sacar() e Saldo que deverá ser implementada por todo o tipo de conta para usar a interface.
Construindo o projeto
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.
Vou definir a interface Conta e mostrar como podemos implementá-la em duas classes concretas : ContaPoupanca e ContaCorrente.
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_Interface e clique no botão OK:
Criando a interface Conta
No menu PROJECT clique em Add Class;
Selecione o template Class e informe o nome IConta.vb e clique em Add;
Para definirmos uma interface no VB .NET temos que usar a palavra-chave Interface antes do nome da interface (IConta) e terminar com a declaração End Interface;
Vamos começar definindo a nossa interface da seguinte com 2 métodos e 1 propriedade:
Veja como deve ficar o código VB .NET da nossa interface IConta :
Public Interface IConta
Function Depositar(valor As Decimal) As Boolean
Function Sacar(valor As Decimal) As Boolean
ReadOnly Property Saldo() As Decimal
End Interface
|
Note que temos apenas a declaração da propriedade e dos métodos mas não a sua implementação. A implementação destes membros deverá ser feita pelas classes concretas.
Criando a classe ContaPoupanca e implementando a interface IConta
Vamos criar agora a classe concreta ContaPoupanca.
No menu PROJECT clique em Add Class;
Selecione o template Class e informe o nome ContaPoupanca.vb e clique em Add;
A seguir digite logo abaixo da declaração da classe a palavra Implements e a seguir a interface IConta:
Ao teclar ENTER o Visual Studio irá criar automaticamente os métodos e propriedades da interface que devemos implementar conforme mostra a figura abaixo:
Vamos definir duas variáveis privadas na classe ContaPoupanca:
Private _saldo As
Decimal
Private _limiteDiario As Decimal
1- Implementando o método Depositar
Vamos implementar o método Depositar conforme o código abaixo:
Public Function Depositar(valor As Decimal) As Boolean Implements IConta.Depositar
_saldo += valor
Console.WriteLine(String.Format("Deposito realizado com sucesso : {0,6:C}", valor))
Return True
End Function
|
O método Depositar da ContaPoupanca irá incrementar o valor do saldo da conta pelo valor do depósito e retornar um valor igual a True.
2- Implementando o método Sacar
No método Sacar temos que verificar se existe saldo na conta e se o valor do saque é superior ao limite diário (definido como R$ 1.000,00 ).
Se houver saldo e o valor do saque estiver dentro do valor limite iremos exibir uma mensagem de saque realizado com sucesso.
A seguir temos a implementação do método Sacar() para a classe ContaPoupanca:
Public Function Sacar(valor As Decimal) As Boolean Implements IConta.Sacar
If _saldo < valor Then
Console.WriteLine("Saldo insuficiente.")
Return False
ElseIf _limiteDiario + valor > 1000 Then
Console.WriteLine("Valor superior ao limite diário!")
Return False
Else
_saldo -= valor
_limiteDiario += valor
Console.WriteLine(String.Format("Saque realizado com sucesso : {0,6:C}", valor))
Return True
End If
End Function
|
3- Implementando a propriedade Saldo
A propriedade Saldo apenas permite que o seu valor seja lido não podendo ser alterado diretamente fora da classe. A isso chamamos encapsulamento. Dessa forma o valor do Saldo somente poderá ser alterado usando os métodos Sacar() e Depositar() da própria classe.
A seguir temos o código da implementação da propriedade Saldo:
Public ReadOnly Property Saldo As Decimal Implements IConta.Saldo
Get
Return _saldo
End Gil
End Property
|
4- Sobrescrevendo o método ToString()
Vamos também sobrescrever o método ToString() que retorna uma string que representa o objeto atual. Esse método é um método do .NET Framework e como cada classe no VB .NET herda de Object , cada objeto no VB .NET contém o método ToString(). Podemos sobrescrever o método para criar uma mensagem personalizada que desejamos usar em nossa classe.
É isso que fizemos a seguir sobrescrevendo o método ToString() da classe Object:
Public Overrides Function ToString() As String
Return String.Format("Saldo da Conta de Poupança = {0,6:C}", _saldo)
End Function
|
E assim temos o código completo da classe ContaPoupanca que implementa os métodos e propriedades da interface IConta:
Public Class ContaPoupanca Implements IConta
Private
_saldo As Decimal
Public Function Depositar(valor As Decimal) As Boolean
Implements IConta.Depositar
Public Function Sacar(valor As Decimal) As Boolean Implements IConta.Sacar
Public ReadOnly Property Saldo As Decimal Implements IConta.Saldo
Public
Overrides Function ToString() As String End Class |
Criando a classe ContaCorrente e implementando a interface IConta
Vamos agora criar a classe concreta ContaCorrente.
No menu PROJECT clique em Add Class;
Selecione o template Class e informe o nome ContaCorrente.vb e clique em Add;
A seguir digite logo abaixo da declaração da classe a palavra Implements e a seguir a interface IConta.
Ao teclar ENTER o Visual Studio irá criar automaticamente os métodos e propriedades da interface que devemos implementar conforme mostra a figura abaixo:
Nesta classe vamos definir apenas uma variável privada visto que não teremos valor para limite diário de saque.
Private _saldo As
Decimal
1- Implementando o método Depositar
Vamos implementar o método Depositar conforme o código abaixo:
Public Function Depositar(valor As Decimal) As Boolean Implements IConta.Depositar
_saldo += valor
Console.WriteLine(String.Format("Deposito realizado com sucesso : {0,6:C}", valor))
Return True
End Function
|
O método Depositar da ContaCorrente, da mesma forma que a classe ContaPoupanca , irá incrementar o valor do saldo da conta pelo valor do depósito e retornar um valor igual a True e uma mensagem de depósito feito com sucesso.
2- Implementando o método Sacar
No método Sacar temos que verificar apenas se existe saldo na conta.
Se houver saldo iremos exibir uma mensagem de saque realizado com sucesso caso contrário iremos exibir saldo insuficiente.
A seguir temos a implementação do método Sacar() para a classe ContaPoupanca:
Public Function Sacar(valor As Decimal) As Boolean Implements IConta.Sacar
If _saldo < valor Then
Console.WriteLine("Saldo insuficiente.")
Return False
Else
_saldo -= valor
Console.WriteLine(String.Format("Saque realizado com sucesso : {0,6:C}", valor))
Return True
End If
End Function
|
3- Implementando a propriedade Saldo
A seguir temos o código da implementação da propriedade Saldo que é idêntico ao da classe ContaPoupanca:
Public ReadOnly Property Saldo As Decimal Implements IConta.Saldo
Get
Return _saldo
End Gil
End Property
|
4- Sobrescrevendo o método ToString()
Nesta classe também vamos sobrescrever o método ToString() igual a classe ContaPoupanca apenas alterando a mensagem :
Public Overrides Function ToString() As String
Return [String].Format("Saldo da Conta Corrente = {0,6:C}", _saldo)
End Function
|
E assim temos o código completo da classe ContaCorrente que implementa os métodos e propriedades da interface IConta:
Public Class ContaCorrente
Implements IConta
Private _saldo As Decimal
Public Function Depositar(valor As Decimal) As Boolean Implements IConta.Depositar _saldo += valor Console.WriteLine(String.Format("Deposito realizado com sucesso : {0,6:C}", valor)) Return True End Function Public Function Sacar(valor As Decimal) As Boolean Implements IConta.Sacar
If _saldo < valor Then
Console.WriteLine("Saldo insuficiente.")
Return False
Else
_saldo -= valor
Console.WriteLine(String.Format("Saque realizado com sucesso : {0,6:C}", valor))
Return True
End If
End Function
Public ReadOnly Property Saldo As Decimal Implements IConta.Saldo
Get
Return _saldo
End Get
End Property
Public Overrides Function ToString() As String
Return String.Format("Saldo da Conta Corrente = {0,6:C}", Saldo)
End Function
End Class
|
Testando as classes no projeto Console Application
Vamos agora testar a utilização da interface e das classes criadas no projeto em uma aplicação Console Application.
Vamos criar uma instância da classe ContaPoupanca e da classe ContaCorrente e realizar algumas operações de saque e deposito.
O código deverá ser incluído no arquivo Module1.vb conforme abaixo:
Module Module1
Sub Main()
'criando as instãncias das Classes Concretas como sendo do tipo da Interface IConta
Dim contaPoupanca_Macoratti As IConta = New ContaPoupanca()
Dim contaCorrente_Macoratti As IConta = New ContaCorrente()
Console.WriteLine("Testando a conta de poupança." & vbCrLf)
contaPoupanca_Macoratti.Depositar(2000)
contaPoupanca_Macoratti.Sacar(100)
contaPoupanca_Macoratti.Sacar(1000)
contaPoupanca_Macoratti.Sacar(200)
Console.WriteLine(contaPoupanca_Macoratti.ToString())
Console.ReadKey()
Console.WriteLine("Testando a conta corrente." & vbCrLf)
contaCorrente_Macoratti.Depositar(3000)
contaCorrente_Macoratti.Sacar(150)
contaCorrente_Macoratti.Sacar(1000)
contaCorrente_Macoratti.Sacar(90)
contaCorrente_Macoratti.ToString()
Console.WriteLine(contaCorrente_Macoratti.ToString())
Console.ReadKey()
End Sub
End Module
|
Executando o projeto iremos obter o seguinte resultado:
Abaixo vemos exemplos de execução para Poupanca e ContaCorrente:
Vimos assim como podemos criar uma interface e implementar seus métodos em classes concretas.
Nesse momento você pode estar com as seguintes dúvidas:
Quando você deve usar uma classe abstrata ?
Quando você deve usar uma Interface ?
Quando você deve usar as duas ?
A seguir um pequeno roteiro para ajudá-lo a tomar a melhor decisão ....
O que é uma classe abstrata ?
Suponha que vamos criar várias classes que têm
métodos em comum e outros métodos funcionam diferente para cada classe. Uma
forma de fazer isso é usar as classes abstratas.
- As classes abstratas tem pelo menos um método abstrato, ou seja um método que
não tem corpo.
- Se um método tem uma classe abstrata ele deve ser declarado como um método
abstrato.
- Não podem ser criadas instâncias de classes abstratas.
- Ao criar uma classe usando uma classe abstrata como herança devem ser criados
os corpos para os métodos abstratos.
- Para criar uma classe usando uma classe abstrata como herança basta usar a
palavra-chave inherits , como em uma
classe normal
- Um método abstrato é identificado pelo modificador - MustOverride
- , a classe que possui este modificador não pode ser instanciada através
da palavra chave New.
Vamos a um exemplo:
O que são Interfaces ?
Interfaces podem ser entendidas como um tipo de classe abstrata em que todos métodos são abstratos.
- Em uma interface nenhum método tem corpo e
são implicitamente abstratas e publicas
- Assim como uma classe abstrata , uma interface não pode ser instanciada.
- Uma classe pode implementar mais de uma interface
- Uma interface não pode conter um construtor
- Ao criar uma classe usando uma interface devem ser feitos os corpos de todos
os métodos da interface, caso contrario deverá ser criada uma classe abstrata.
- Para implementar uma interface no VB.NET usamos o
modificador - Implements
.
Com os conceitos bem definidos vamos tentar uma tabela de consulta rápido para tomada de decisões:
Interfaces x Classes Abstratas | ||
Característica | Interface | Classe Abstrata |
Herança múltipla | Uma classe pode implementar diversas interfaces | Uma classe pode herdar somente uma classe |
Implementação Padrão | Uma interface não pode conter qualquer tipo de código, muito menos código padrão. | Uma classe abstrata pode fornecer código completo , código padrão ou ter apenas a declaração de seu esqueleto para ser posteriormente sobrescrita. |
Constantes | Suporte somente constantes do tipo estática. | Pode conter constantes estáticas e de instância. |
Componentes de terceiros | Uma implementação de uma interface pode ser incluída a qualquer classe de terceiros. | Uma classe de terceiros precisa ser reescrita para estender somente a partir da classe abstrata. |
Homogeneidade | Se todas as diversas implementações compartilham a assinatura do método então a interface funciona melhor. | Se as várias implementações são todas do tipo e compartilham um comportamento e status comum , então a classe abstrata funciona melhor. |
Manutenção | Se o código do seu cliente conversa somente em termos de uma interface, você pode facilmente alterar a implementação concreta usando um método factory. | idêntico |
Velocidade | Lento , requer trabalho extra para encontrar o método correspondente na classe atual. | Rápido |
Clareza | Todas as declarações de constantes em uma interface são presumidamente publicas ou estáticas. | Você pode por código compartilhado em uma classe abstrata. Você pode usar código para computar o valor inicial de suas constantes e variáveis de instância ou estáticas. |
Funcionalidades Adicionais | Se você incluir um novo método em uma interface você precisa ajustar todas as implementações da interface. | Se você incluir um novo método em uma classe abstrata você tem a opção de fornecer uma implementação padrão para ele. |
Você decide. !
Pegue o projeto completo aqui: OOP_Interface.zip
Na próxima aula irei abordar os conceitos sobre polimorfismo e sua implementação e utilização na linguagem Visual Basic.
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