Desenvolvimento - Visual Basic .NET
POO – Programação Orientada a Objetos – Parte 2
Vamos ver na prática como utilizar a Programação Orientada a Objetos utilizando como referência o artigo POO – Programação Orientada a Objetos Parte 1.
por David PomaricoSituação:
Elaborar um Cadastro de Clientes. Os dados serão incluídos em um banco de dados Access 2000.
Diagrama de Classes
Criando as Classes e adicionando funcionalidades
Cliente
Adicionamos dois atributos private para a classe de Cliente, um método chamado Gravar e outro chamado Retornar. Agora vamos adicionar as Property para retornar ou setar o valor dos atributos, utilizando assim o encapsulamento de atributos.
Private _cliCodigo As Integer Public Property cliCodigo() As Integer Get Return _cliCodigo End Get Set(ByVal Value As Integer) _cliCodigo = Value End Set End Property Private _cliNome As String Public Property cliNome() As String Get Return _cliNome End Get Set(ByVal Value As String) _cliNome = Value End Set End Property Private _cliTelefone As String Public Property cliTelefone() As String Get Return _cliTelefone End Get Set(ByVal Value As String) _cliTelefone = Value End Set End Property
Feito isso, devemos implementar o método Gravar e Retornar da classe de clientes. Porém, sabemos que existem dois tipos de clientes, Pessoa Física e Pessoa Jurídica. Então como vamos Gravar ou Retornar um cliente sem os atributos que estão nas classes derivadas?
Para tal procedimento devemos fazer algumas alterações:
- Adicionar a palavra MustInherit na classe clsCliente, indicando que esta classe tem de ser herdada.
- Adicionar a palavra Overridable indicando que podemos sobrepor o método Gravar() da classe.
- Adicionar a palavra Overridable indicando que podemos sobrepor o método Retornar() da classe.
- Adicionar o método Construtor de nossa classe.
- Adicionar o método Construtor fazendo uma sobrecarga.
Assim ficará nossa classe clsCliente:
Public MustInherit Class clsCliente Private _cliCodigo As Integer Public Property cliCodigo() As Integer Get Return _cliCodigo End Get Set(ByVal Value As Integer) _cliCodigo = Value End Set End Property Private _cliNome As String Public Property cliNome() As String Get Return _cliNome End Get Set(ByVal Value As String) _cliNome = Value End Set End Property Private _cliTelefone As String Public Property cliTelefone() As String Get Return _cliTelefone End Get Set(ByVal Value As String) _cliTelefone = Value End Set End Property Public Overridable Sub Gravar() End Sub Public Overridable Function Retornar() As DataSet End Function Public Sub New() End Sub Public Sub New(ByVal Codigo As Integer, ByVal Nome As String, ByVal Telefone As String) cliCodigo = Codigo cliNome = Nome cliTelefone = Telefone End Sub End ClassPessoa Física
Devemos fazer o mesmo que a classe de cliente, adicionar os atributos e métodos. Criaremos dois Contrutores New para fazer a sobrecarga.
Veja como ficou nossa classe clsPessoaFisica:
Public Class clsPessoaFisica Inherits clsCliente Private _pefCPF As String Public Property pefCPF() As String Get Return _pefCPF End Get Set(ByVal Value As String) _pefCPF = Value End Set End Property Private _pefRG As String Public Property pefRG() As String Get Return _pefRG End Get Set(ByVal Value As String) _pefRG = Value End Set End Property Public Sub New() End Sub Public Sub New(ByVal CPF As String, ByVal RG As String) pefCPF = CPF pefRG = RG End Sub End Class
Vamos implementar o método Gravar de Pessoa Física. Para isso devemos utilizar os atributos da classe pai e da classe filha para que possamos gravar os dados do cliente. Note que devemos adicionar a palavra Overrides que indica que iremos sobrepor o método Gravar() da classe pai.
Public Overrides Sub Gravar() Dim strConexao As String = System.Configuration.ConfigurationSettings.AppSettings("Conexao") "Declaro a conexao Dim con As New OleDbConnection(strConexao) "Declaro um objeto OleDbCommand Dim cmd As New OleDbCommand "Este é o modo que declaro meus paramentros. Faça do jeito que achar melhor. Dim prmParametro = New OleDbParameter(3) {} prmParametro(0) = New OleDbParameter("@cliNome", MyBase.cliNome) prmParametro(1) = New OleDbParameter("@cliTelefone", MyBase.cliTelefone) prmParametro(2) = New OleDbParameter("@pefCPF", pefCPF) prmParametro(3) = New OleDbParameter("@pefRG", pefRG) "Monto a string de SQL para inserir no banco Dim strSQL As New Text.StringBuilder strSQL.Append("insert into tblCliente ") strSQL.Append("(cliNome, cliTelefone, cliCPF, cliRG) ") strSQL.Append("values ") strSQL.Append("(@cliNome, @cliTelefone, @cliCPF, @cliRG)") "Adiciono os parametros no meu objeto OleDbCommand Dim p As OleDbParameter For Each p In prmParametro cmd.Parameters.Add(p) Next Try "Abre conexao con.Open() "Seta a conexao cmd.Connection = con "Defino o tipo de Command. cmd.CommandType = CommandType.Text "Passo o comando a ser executado. cmd.CommandText = strSQL.ToString "Executo cmd.ExecuteNonQuery() Catch OleDbEx As OleDbException Throw New Exception(OleDbEx.Message) Catch ex As Exception Throw New Exception(ex.Message) Finally If Not IsNothing(cmd) Then cmd.Dispose() End If If con.State <> ConnectionState.Closed Then con.Close() con.Dispose() End If End Try End Sub
Agora vamos implementar o método que irá retornar os dados de clientes do tipo Pessoa Física. Fiz um método bem simples somente para demonstração.
Public Overrides Function Retornar() As DataSet Dim strConexao As String = System.Configuration.ConfigurationSettings.AppSettings("Conexao") "Declaro a conexao Dim con As New OleDbConnection(strConexao) "Declaro um objeto OleDbCommand Dim cmd As New OleDbCommand "Monto a string de SQL para inserir no banco Dim strSQL As New Text.StringBuilder strSQL.Append("SELECT cliCodigo, cliNome, ") strSQL.Append("cliTelefone, cliCPF, cliRG ") strSQL.Append("FROM tblCliente WHERE cliCNPJ IS NULL;") cmd.Connection = con cmd.CommandType = CommandType.Text cmd.CommandText = strSQL.ToString() Dim da As New OleDbDataAdapter(cmd) Dim ds As New DataSet Try "Abre conexao con.Open() "Preencho o DataSet com os dados da.Fill(ds) Catch OleDbEx As OleDbException Throw New Exception(OleDbEx.Message) Catch ex As Exception Throw New Exception(ex.Message) Finally If Not IsNothing(cmd) Then cmd.Dispose() End If If con.State <> ConnectionState.Closed Then con.Close() con.Dispose() End If End Try Return ds End FunctionPessoa Jurídica
Devemos fazer o mesmo que a classe de Pessoa Física, porém o que vai ser diferente é a forma de implementação do método Gravar(), Retornar() e os construtores da classe.
Veja como ficará nossa classe de Pessoa Jurídica:
Public Class clsPessoaJuridica Inherits clsCliente Private _pejCNPJ As String Public Property pejCNPJ() As String Get Return _pejCNPJ End Get Set(ByVal Value As String) _pejCNPJ = Value End Set End Property Private _pejInscricaoEstadual As String Public Property pejInscricaoEstadual() As String Get Return _pejInscricaoEstadual End Get Set(ByVal Value As String) _pejInscricaoEstadual = Value End Set End Property Private _pejNomeFantasia As String Public Property pejNomeFantasia() As String Get Return _pejNomeFantasia End Get Set(ByVal Value As String) _pejNomeFantasia = Value End Set End Property Public Sub New() End Sub Public Sub New(ByVal CNPJ As String, ByVal NomeFantasia As String, ByVal InscricaoEstadual As String) pejCNPJ = CNPJ pejNomeFantasia = NomeFantasia pejInscricaoEstadual = InscricaoEstadual End Sub Public Overrides Sub Gravar() Dim strConexao As String = System.Configuration.ConfigurationSettings.AppSettings("Conexao") "Declaro a conexao Dim con As New OleDbConnection(strConexao) "Declaro um objeto OleDbCommand Dim cmd As New OleDbCommand "Este é o modo que declaro meus paramentros. Faça do jeito que achar melhor. Dim prmParametro = New OleDbParameter(4) {} prmParametro(0) = New OleDbParameter("@cliNome", MyBase.cliNome) prmParametro(1) = New OleDbParameter("@cliTelefone", MyBase.cliTelefone) prmParametro(2) = New OleDbParameter("@pejCPNPJ", pejCNPJ) prmParametro(3) = New OleDbParameter("@pejNomeFantasia", pejNomeFantasia) prmParametro(4) = New OleDbParameter("@pejInscricaoEstadual", pejInscricaoEstadual) "Monto a string de SQL para inserir no banco Dim strSQL As New Text.StringBuilder strSQL.Append("insert into tblCliente ") strSQL.Append("(cliNome, cliTelefone, cliCNPJ, cliInscricaoEstadual, cliNomeFantasia) ") strSQL.Append("values ") strSQL.Append("(@cliNome, @cliTelefone, @cliCNPJ, @cliInscricaoEstadual, @cliNomeFantasia)") "Adiciono os parametros no meu objeto OleDbCommand Dim p As OleDbParameter For Each p In prmParametro cmd.Parameters.Add(p) Next Try "Abre conexao con.Open() "Seta a conexao cmd.Connection = con "Defino o tipo de Command. cmd.CommandType = CommandType.Text "Passo o comando a ser executado. cmd.CommandText = strSQL.ToString "Executo cmd.ExecuteNonQuery() Catch OleDbEx As OleDbException Throw New Exception(OleDbEx.Message) Catch ex As Exception Throw New Exception(ex.Message) Finally If Not IsNothing(cmd) Then cmd.Dispose() End If If con.State <> ConnectionState.Closed Then con.Close() con.Dispose() End If End Try End Sub Public Overrides Function Retornar() As DataSet Dim strConexao As String = System.Configuration.ConfigurationSettings.AppSettings("Conexao") "Declaro a conexao Dim con As New OleDbConnection(strConexao) "Declaro um objeto OleDbCommand Dim cmd As New OleDbCommand "Monto a string de SQL para inserir no banco Dim strSQL As New Text.StringBuilder strSQL.Append("SELECT cliCodigo, cliNome, ") strSQL.Append("cliTelefone, cliNomeFantasia, ") strSQL.Append("cliInscricaoEstadual, cliCNPJ ") strSQL.Append("FROM tblCliente WHERE cliCPF IS NULL;") cmd.Connection = con cmd.CommandType = CommandType.Text cmd.CommandText = strSQL.ToString() Dim da As New OleDbDataAdapter(cmd) Dim ds As New DataSet Try "Abre conexao con.Open() "Preencho o DataSet com os dados da.Fill(ds) Catch OleDbEx As OleDbException Throw New Exception(OleDbEx.Message) Catch ex As Exception Throw New Exception(ex.Message) Finally If Not IsNothing(cmd) Then cmd.Dispose() End If If con.State <> ConnectionState.Closed Then con.Close() con.Dispose() End If End Try Return ds End Function End ClassPergunta
Preciso montar uma function que irá retornar um DataSet. Porém eu preciso passar parâmetros para um objeto do tipo Command. E agora como eu faço?
Resposta
Simples. Pergunte sempre se você irá precisar do objeto preenchido para fazer tal procedimento. Se a resposta for sim, utilize o método New que irá lhe retornar um objeto preenchido. Caso a resposta seja não, utilize o método como Shared e chame o método que irá retornar o DataSet passando o parâmetro necessário através de ByVal ou ByRef. Ficaria assim:
Deste modo eu não preciso alocar o objeto na memória e com isso reduzirei a utilização da mesma.
Agora vamos criar dois formulários para podermos utilizar as classes criadas. Um formulário será o de cadastro de cliente e o outro para pesquisar clientes (sem filtro). Criei o formulário de cadastro de cliente com 2 groupbox para poder exibir dados específicos de Clientes do tipo de pessoa física e pessoa jurídica. Veja figura abaixo:
Agora vamos implementar o código no botão Gravar.
Try Dim clsCliente As Classes.clsCliente If optFisica.Checked = True AndAlso optJuridica.Checked = False Then "Se for pessoa Fisica Dim clsFisica As New Classes.clsPessoaFisica clsFisica.pefCPF = txtCPF.Text clsFisica.pefRG = txtRG.Text clsCliente = clsFisica ElseIf optJuridica.Checked = True AndAlso optFisica.Checked = False Then "Se for pessoa Jurídica Dim clsJuridica As New Classes.clsPessoaJuridica clsJuridica.pejCNPJ = txtCNPJ.Text clsJuridica.pejInscricaoEstadual = txtInscricaoEstadual.Text clsJuridica.pejNomeFantasia = txtNomeFantasia.Text clsCliente = clsJuridica End If clsCliente.cliNome = txtNome.Text clsCliente.cliTelefone = txtTelefone.Text clsCliente.Gravar() Catch OleDbex As OleDb.OleDbException MessageBox.Show(OleDbex.Message.ToString()) Catch ex As Exception MessageBox.Show(ex.Message.ToString()) Finally MessageBox.Show("Cliente gravado com sucesso!") End Try
Se você reparar na figura do formulário de cadastro, poderá perceber que criei um botão chamado Pesquisar. Este botão irá chamar outro formulário que trará os clientes de acordo com a seleção de um RadioButton. Veja figura abaixo:
Agora vamos adicionar o código que irá retornar um DataSet e irá preencher os dados do DataGrid.
Dim clsCliente As Classes.clsCliente If optFisica.Checked = True AndAlso optJuridica.Checked = False Then Dim clsFisica As New Classes.clsPessoaFisica clsCliente = clsFisica ElseIf optJuridica.Checked = True AndAlso optFisica.Checked = False Then Dim clsJuridica As New Classes.clsPessoaJuridica clsCliente = clsJuridica Else MessageBox.Show("Selecione um tipo de cliente!") End If dgdGrid.DataSource = clsCliente.Retornar()
Pronto, agora basta testar se sua aplicação está gravando no banco de dados e exibindo os dados no DataGrid.
Observações:
Preste muita atenção no código de gravação e pesquisa de clientes. Veja que declarei uma variável clsCliente do tipo da classe de cliente. Depois fiz a verificação de qual tipo de cliente o meu usuário está trabalhando (Física ou Jurídica). Após isso eu atribui minha variável de tipo de cliente, física ou jurídica, na variável clsCliente e chamei o método gravar() e pesquisar(). Fazendo isso o sistema irá saber com qual cliente eu estou trabalhando e irá chamar o método devido. Se eu precisar adicionar um novo tipo de cliente eu apenas vou fazer a validação no IF e setar minha variável clsCliente com o novo tipo de cliente e esta irá chamar o método Override da minha nova classe.
Quando utilizar Overloads?
Se você não colocar a palavra-chave Overloads, seus métodos vão funcionar com sobrecarga normalmente. Mas para deixar de forma explícita e de fácil entendimento para outro desenvolvedor utilize Overloads sempre que você criar funções ou procedimentos com o mesmo nome. A única restrição do Overloads é criar funções ou procedimentos com parâmetros com o mesmo tipo de dados, ou seja, com a mesma assinatura. Por exemplo:
Por que, na classe clsCliente, você utilizou a palavra-chave Overridable sendo que o método não está implantado?
Fiz isso somente para mostrar como fazer. Como o meu método não está implementado o correto seria utilizar a palavra-chave MustOverride. Sendo assim eu criaria apenas a assinatura do método e nas classes derivadas eu faria a implementação do método. Ficaria assim:
No início é um pouco complicado saber quando usar o que, mas com o tempo, estudo e dedicação você irá saber qual palavra-chave e tipos de implementação utilizar sem muitos problemas.
Minha dica é: faça, sempre que possível, uma revisão de seu código. Se você encontrar Functions de validação, acesso a banco e cálculos mirabolantes é porque algo está errado. Utilize SEMPRE as classes.
Caso esqueça de alguma implementação ou palavra-chave, utilize o artigo POO – Programação Orientada a Objetos Parte 1 como guia de referência.
Estou disponibilizando o projeto, banco de dados (Access 2000) e o diagrama de classes feito no Visio Enterprise Architects.
Para baixar o projeto completo, clique aqui.
Até a próxima!
David Pomarico
- Entity Framework 4: Repositório GenéricoVisual Basic .NET
- As edições 14 da Easy .net Magazine e 88 da .net Magazine já estão disponíveis.ADO.NET
- Postando no Twiiter com .NET e Migre.meC#
- Setup ApplicationsVisual Basic .NET
- Problemas na manipulação de arquivos do MS Excel com .NETVisual Basic .NET