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. Vimos como criar métodos e propriedades na classe base e como especializar essa classe criando classes derivadas. Vimos 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 – 06
Nesta aplicação você vai aprender a definir e utilizar interfaces.
Objetivo: Criar uma pequena aplicação para controlar os saques, depósitos e saldos de uma conta pessoal usando os conceitos de 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 e é 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 fôssemos criar uma conta desse tipo.
Criamos, então, uma classe base Conta abstrata e nela 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.
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 e seus membros são sempre públicos e não podem ser declarados como estáticos (static), nem como overridable. Isso significa que os métodos não podem ser sobrepostos e 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 outros 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 no 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 |
- Uma interface no VB.NET não pode conter campos; somente métodos, propriedades e eventos;
- Todos os membros de uma interface são públicos e não podem usar um modificador de acesso;
- Na classe que implementa a interface, cada implementação do método precisa especificar o método da interface que ele implementa usando a palavraImplements, seguido pelo nome da interface o nome do método;
- O nome da interface e o nome do método são separados por dois pontos(:).
Podemos criar para o nosso exemplo uma interface, ao invés de uma classe abstrata, como fizemos na aula anterior. Podemos criar uma interface para Contacontendo 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:
- Saldo() – propriedade somente leitura;
- Depositar() – método que permite sacar um valor da conta;
- Sacar() – método que permite depositar um valor da conta.
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:
- _saldo – armazena o valor do saldo da conta;
- _limiteDiario – define o valor limite diário para realização de saques.
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 mil).
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 Private _limiteDiario 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 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 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 de Poupança = {0,6:C}", Saldo) End Function 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.
- _saldo – armazena o valor do saldo da conta
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, 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 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 têm 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 públicas;
- 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 contrário 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.