.NET

12 ago, 2014

Programação Orientada a Objetos em 10 lições práticas – Parte 03

Publicidade

Na primeira parte deste artigo apresentei os conceitos chaves da orientação a objetos na linguagem VB .NET, e agora vamos mostrar como criar uma aplicação VB .NET aplicando os conceitos abordados.

Lição 10 – Juntando todas as partes

Embora o 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 é 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.

Criando sua primeira aplicação orientada a objetos com VB .NET

Nesta primeira aplicação você vai aprender a:

  • Decidir quais classes implementar em seu programa;
  • Criar classes com campos, propriedades e métodos;
  • Usar classes em uma aplicação Windows Forms;
  • Usar o Visual Studio 2012 Express for desktop para criar classes;
  • Criar uma aplicação Windows Forms e usar classes nesta aplicação;
  • Aprender como interagir com controles de formulário.

O objetivo é criar uma aplicação Windows Forms que exiba textos em tamanhos de páginas específicos.

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 e 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.

  1. Problema: Você possui baixado no seu computador diversos livros e deseja selecionar um livro e ler uma página particular, podendo definir o tamanho desta página.
  2. Interface: A interface da aplicação foi criada no Visual Studio 2012 Express for desktop e utiliza os controles ListBox, RichTextBox, Labels, NumericUpDown.

Construindo a interface

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 LeitorVBNET e clique no botão OK:

vbn_oop21

A seguir, vamos incluir os seguintes controles no formulário form1.vb:

  • Label
  • ListBox – name=lbLivros
  • RichtTextBox – name=rchtPagina
  • NumericUpDown – name=nupd_TamanhoPagina
  • NumericUpDown – name=nupd_PaginaExibir

O leiaute do formulário é visto abaixo:

vbn_oop22

Criar a interface usando o Visual Studio 2012 Express for desktop é bem simples, mas agora nossa preocupação é saber:

  • Como armazenar os textos dos livros?
  • Como preencher a lista?
  • Como retornar a página correta do livro que desejamos ler?

Para responder essas perguntas, vamos usar os conceitos da programação orientada a objetos.

Definindo as classes

Antes que você possa implementar suas classes, você deve decidir quais as classes que você precisa. Primeiro você deve olhar para os objetos do problema.

Tendo encontrado os objetos, então você olha para as propriedades, que são características ou qualidades que pertencem ao objeto e os métodos, que são os comportamentos do objeto.

Você pode escolher entre muitas maneiras de projetar as classes em um aplicativo. A abordagem aqui apresentada começa com uma análise textual do problema. Os substantivos são selecionados como candidatos às classes, enquanto os verbos se tornam candidatos aos métodos.

No curso da análise, você vai eliminar muitos dos substantivos como candidatos, e você pode descobrir classes que não estão entre os substantivos na especificação.

Depois de determinar os objetos, propriedades e métodos que pertencem a suas classes, você pode escrever a especificação da classe que você vai usar na implementação.

Encontrando as classes

1. lendo o texto do problema e identificando todos os substantivos:

Você possui baixado no seu computador o texto de diversos livros e deseja selecionar um livro e ler uma página particular por vez podendo definir o tamanho desta página.

Podemos eliminar computador, texto, tamanho e página pois são irrelevantes para o problema, não podendo gerar comportamento para qualificar uma classe.

Ficamos então com livro e o seu plural livros, que podem representar classes potenciais para expressar o domínio do nosso problema.

Nosso problema deverá tratar com livro, onde um livro contém um título e um texto que pode ser lido, e livros, onde livros representa uma coleção de livros e que por isso vamos chamar de Livraria.

Definimos, portanto, duas classes no problema: Livro e Livraria.

Encontrando propriedades e métodos

2. lendo o texto do problema e identificando todos os verbos:

Você possui baixado no seu computador o texto de diversos livros e deseja selecionar um livro e ler uma página particular por vez podendo definir o tamanho desta página.

Considerando cada verbo devemos verificar se ele é um método ou pode indicar um método e se é relevante para o problema. Assim temos:

  • Selecionar pode ser considerado uma operação da classe Livraria, onde devemos selecionar um livro dentre os livros existentes, marcando para leitura.Vamos definir este método como SelecionarLivro.
  • Ler é operação da classe Livro. Este método permitirá ler uma página particular e portanto vamos chamá-lo de getPagina.
  • Adicionar – Devemos poder incluir livros na Livraria. Portanto, o método Adicionar seria responsável por essa operação. Vamos chamar o método de AdiconarLivro.

Propriedades da classe Livro:

  • Texto
  • Tamanho da página- TamanhoPagina
  • Titulo

Vamos, então, verificar se estamos no caminho certo.

Podemos armazenar e organizar diversos livros ? Sim, podemos criar um Livro e armazenar cada livro formando um Livraria usando o método AdicionarLivro.

Podemos selecionar um livro e ler uma página do livro por vez ? Sim, podemos selecionar um livro pelo título usando o método SelecionarLivro e usar o método getPagina para retornar uma página.

Podemos definir o tamanho da página? Sim, podemos usar a propriedade TamanhoPagina para definir o tamanho da página.

Percebemos que estamos indo na direção certa. Vamos relacionar os métodos e propriedades das nossas classes:

Classe Propriedades Métodos
Livro TamanhoPagina – Integer
  • GetPagina( numeroPagina as integer) as String
Texto – String
Titulo – String
Livraria
  • SelecionarLivro(titulo as string) as Livro
  • AdicionarLivro(aLivro as Livro)

Criando a classe Livro

No menu PROJECT, clique em Add Class. Selecione o template Class e informe o nome Livro.vb e clique em Add:

vbn_oop23

A seguir, vamos definir na classe Livro o seguinte código:

Public Class Livro

    '1 - construtor
    Sub New()
    End Sub

    '2 - campos
    Public Texto As String = ""
    Public TamanhoPagina As Integer = 10

    '3 - propriedade 
    Public Property Titulo As String

    '4 - método
    Public Function GetPagina(ByVal numeroPagina As Integer) As String
        Dim inicio As Integer = (numeroPagina - 1) * TamanhoPagina
        If (inicio < Texto.Length) And (inicio >= 0) Then
            If (inicio + TamanhoPagina) < Texto.Length Then
                Return Texto.Substring(inicio, TamanhoPagina)
            Else
                Return Texto.Substring(inicio, Texto.Length - inicio)
            End If
        Else
            Return ""
        End If
    End Function

End Class

Vamos entender o código:

O modificador Public na classe Livro: Public Class Livro, indica que a classe poderá ser usada e acessada em todo o projeto.

A classe Livro possui um construtor padrão vazio definido como:

Sub New()
End Sub

Geralmente, o construtor contém código para inicializar os campos das classes e realizar outras operações de inicialização. Ele será executado toda vez que a classe for instanciada com o operador new.

Não é obrigatório definir um construtor. Em nosso exemplo eu apenas declarei o construtor para mostrar como é a sintaxe da declaração no VB .NET.

Definimos os campos (fields) Texto e TamanhoPagina como sendo do tipo String e Integer e atribuindo valores iniciais aos mesmos:

Public Texto As String = ""
Public TamanhoPagina As Integer = 10

Um campo é uma variável declarada na classe e pode ser de qualquer tipo de dados da plataforma .NET

Se não tivéssemos atribuído valores iniciais aos campos, os valores default seriam atribuídos pelo compilador. Para campos do tipo String, um valor “” seria atribuído e para campos Integer, seria atribuído o valor zero.

Os campos utilizam o modificar Public, significando que podem ser acessados sem restrição.

O acesso direto aos dados de uma classe é uma violação de um princípio básico da orientação a objeto: o encapsulamento da informação. Por isso definimos propriedades para acessar os campos, sendo que eles são declarados com Private e as propriedades como Public.

A propriedade Titulo foi definida usando a nova sintaxe das propriedades auto implementadas: Public Property Titulo As String.

A sintaxe antiga, usada pelo VB .NET, usava as declarações get/set nas propriedades – onde get obtinha o valor e set atribuía valores. Abaixo vemos como ficaria a propriedade Titulo na sintaxe antiga:

private m_titulo as String
Public Property Titulo() As String
   Get
      Return m_titulo
   End Get
      Set(ByVal value As String)
      m_titulo = value
   End Set
End Property

Uma propriedade permite obter e atribuir valores a um campo privado da classe.

A diferença entre propriedade e campo é que para os campos é reservado um valor na memória, pois eles contêm dados. As propriedades só permitem o acesso aos campos e não possuem dados.

As propriedades podem ser Public, Private, somente-leitura (ready-only), somente-escrita (write-only) e podem ser usadas para validar dados da classe e esconder sua implementação.

Podemos visualizar a estrutura da classe usando a opção Class View no menu VIEW:

vbn_oop24

Criando a classe Livraria

No menu PROJECT clique em Add Class;

Selecione o template Class e informe o nome Livraria.vb e clique em Add.

vbn_oop25

A seguir, defina o código abaixo na classe Livraria:

Public Class Livraria

    Private prateleira As New SortedList()

    ''' <summary>
    ''' AdicionarLivro
    ''' </summary>
    ''' <param name="novoLivro"></param>
    ''' <remarks></remarks>
    Public Sub AdicionarLivro(ByVal novoLivro As Livro)
        prateleira.Add(novoLivro.Titulo, novoLivro)
    End Sub

    ''' <summary>
    ''' SelecionarLivro
    ''' </summary>
    ''' <param name="titulo"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function SelecionarLivro(ByVal titulo As String) As Livro
        Dim _livro As Livro
        _livro = CType(prateleira(titulo), Livro)
        prateleira.Remove(titulo)
        Return _livro
    End Function

End Class

Entendendo o código:

Definimos a variável prateleira como uma instância da classe SortedList : Private prateleira As New SortedList().

A classe SortedList é uma classe do .NET Framework existente no namespace System.Collections e representa uma coleção de pares chave/valor que são ordenados pelas chaves e são acessíveis por chave e por índice.

Um elemento SortedList pode ser acessado por sua chave, como um elemento em qualquer implementação de IDictionary, ou por seu índice, como qualquer elemento em uma implementação de IList.

Operações em um SortedList objeto tendem a ser mais lenta do que as operações em um Hashtable o objeto por causa da classificação. No entanto, o SortedList oferece mais flexibilidade, permitindo o acesso aos valores por meio das chaves associadas ou os índices.

Vamos usar a instância da classe SortedList para armazenar e selecionar livros (daí seu nome prateleira), sendo que os livros adicionados serão ordenados automaticamente.

Como definimos a variável prateleira como Private, seu acesso será restrito ao escopo da classe.

No método AdicionarLivro(byval novoLivro as Livro), usamos o método Add do objeto prateleira para incluir um novo livro na coleção. Note que precisamos informar o titulo do livro (chave) e um objeto do tipo Livro (valor).

No método SelecionarLivro(byval titulo as String) definimos um objeto _livro do tipo Livro e estamos localizando o livro pelo título na prateleira, realizando uma conversão forçada (casting) para o tipo Livro: CType(prateleira(titulo), Livro).

Após selecionar o livro, usamos o método Remove do objeto prateleira para remover o livro da mesma e retornamos o livro: Return _livro.

Dessa forma, nossa classe Livraria está pronta para ser usada.

Definindo o código do formulário

Agora podemos retornar ao formulário da aplicação e utilizar os eventos dos controles do formulário para definir as ações que desejamos controlar em nossa aplicação usando as classes definidas e interagindo com o usuário.

É através do formulário, seus controles e eventos que o usuário poderá interagir com a aplicação e usar os recursos implementados em nossas classes.

Se você visualizar o código de um formulário, vai perceber que ele é uma classe. No nosso exemplo note a declaração Public Class Form1 explicitando a definição do formulário Form1:

Public Class Form1
End Class

Dessa forma, os formulários que usamos em qualquer projeto VB .NET são classes e possui diversos métodos e eventos, alguns dos quais iremos usar em nossa aplicação.

Vamos iniciar definindo uma variável do tipo Livraria no início da classe Form1:

Private _livraria As Livraria

Isso é necessário para que ela seja visível em todo o formulário. Como definimos a variável como Private, ela somente será visível neste formulário.

Agora vamos usar o evento Load do formulário, que ocorre quando ele é carregado pela primeira vez, definindo o seguinte código neste evento:

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        CarregaDados()
    End Sub

Dessa forma, toda vez que esse formulário for aberto, o evento Load será chamado e a rotina CarregaDados() será executada.

Na rotina CarregaDados() vamos criar uma instância da Livraria e criar dois objetos da classe Livro, adicionando-os na Livraria.

Para isso, digite o código abaixo na rotina CarregaDados:

 Private Sub CarregaDados()
        _livraria = New Livraria()

        Dim _receitas As New Livro()
        _receitas.Texto = "Bolo de chocolate com cobertura de morango é uma delício."
        _receitas.TamanhoPagina = 8
        _receitas.Titulo = "Receitas"

        Dim _contos As New Livro()
        _contos.Texto = "Era uma vez nos tempos dos cavalheiros e das cruzadas."
        _contos.TamanhoPagina = 8
        _contos.Titulo = "Rei Artur"

        _livraria.AdicionarLivro(_receitas)
        _livraria.AdicionarLivro(_contos)

        lbLivros.Items.Add(_receitas.Titulo)
        lbLivros.Items.Add(_contos.Titulo)

    End Sub

Criamos uma instância da classe Livraria : _livraria para podemos adicionar os livros.

A seguir, criamos duas instâncias da classe Livro : _receitas e _contos e atribuí valores às suas propriedades Texto, TamanhoPagina e Título.

Usando o método AdicionarLivro(), incluímos os livros na livraria e para exibir os valores do dos títulos dos livros no controle ListBox (lbLivros), usamos o método Add do controle. Esta faltando exibir a página do livro no controle RichTextBox. Para isso, o usuário deverá selecionar um livro exibido no controle ListBox e sua página será exibida no controle RichTextBox.

Vamos usar o evento SelectedIndexChanged do controle ListBox.

Esse evento ocorre quando houver qualquer mudança na propriedade SelectedIndex do controle. Quando um usuário seleciona um item no ListBox essa propriedade muda de valor e o evento é disparado.

Para abrir o código do evento no formulário basta clicar duas vezes sobre o controle ou na janela de propriedades clicar no ícone para exibir as propriedades e clicar duas vezes sobre a propriedade SelectedIndexChanged:

vbn_oop27

Inclua o código abaixo neste evento:

    Private Sub lbLivros_SelectedIndexChanged(sender As Object, e As EventArgs) Handles lbLivros.SelectedIndexChanged

        Dim _titulo As String = lbLivros.SelectedItem.ToString()
        Dim _livro As Livro = _livraria.SelecionarLivro(_titulo)

        _livro.TamanhoPagina = nupd_TamanhoPagina.Value

        lblTituloLivro.Text = _livro.Titulo

        rchtPagina.Text = _livro.GetPagina(nupd_PaginaExibir.Value)

        _livraria.AdicionarLivro(_livro)

    End Sub

Entendendo o código:

Obtemos o título do livro selecionando no controle ListBox usando o método SelectedItem do controle e usamos o método ToString() para converter o valor para String : Dim _titulo As String = lbLivros.SelectedItem.ToString() e atribuímos o valor a variável _titulo do tipo String (String é um tipo de dados onde armazenamos valores alfanuméricos).

Procuramos o livro na livraria usando o método SelecionarLivro e passando o titulo do livro: Dim _livro As Livro = _livraria.SelecionarLivro(_titulo). O valor retornado é um livro que será armazenado no objeto _livro.

A seguir, atribuímos o valor definido no controle NumericUpDown nupd_TamanhoPagina : _livro.TamanhoPagina = nupd_TamanhoPagina.Value

Obtendo o tamanho da página

Atribuímos o valor do título do livro à Label lblTituloLivro. Obtemos a página usando o método GetPagina() e passando o valor definido no controle nupd_PaginaExibir para página a exibir:

Adicionamos o livro na livraria: _livraria.AdicionarLivro(_livro)

Abaixo vemos o código completo do formulário Form1:

Public Class Form1

    Private _livraria As Livraria

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        CarregaDados()
    End Sub
    Private Sub CarregaDados()
        _livraria = New Livraria()

        Dim _receitas As New Livro()
        _receitas.Texto = "Bolo de chocolate com cobertura de morango é uma delício."
        _receitas.TamanhoPagina = 8
        _receitas.Titulo = "Receitas"

        Dim _contos As New Livro()
        _contos.Texto = "Era uma vez nos tempos dos cavalheiros e das cruzadas."
        _contos.TamanhoPagina = 8
        _contos.Titulo = "Rei Artur"

        _livraria.AdicionarLivro(_receitas)
        _livraria.AdicionarLivro(_contos)

        lbLivros.Items.Add(_receitas.Titulo)
        lbLivros.Items.Add(_contos.Titulo)

    End Sub

    Private Sub lbLivros_SelectedIndexChanged(sender As Object, e As EventArgs) Handles lbLivros.SelectedIndexChanged

        Dim _titulo As String = lbLivros.SelectedItem.ToString()
        Dim _livro As Livro = _livraria.SelecionarLivro(_titulo)

        _livro.TamanhoPagina = nupd_TamanhoPagina.Value

        lblTituloLivro.Text = _livro.Titulo

        rchtPagina.Text = _livro.GetPagina(nupd_PaginaExibir.Value)

        _livraria.AdicionarLivro(_livro)

    End Sub
End Class

Executando o projeto e selecionando um título, vemos o resultado a seguir:

vbn_oop26

Pegue o projeto completo aqui: LeitorVBNET.zip

Na próxima aula irei mostrar como podemos usar herança e criar classes especializadas.