Autor: José Carlos Macoratti - macoratti@yahoo.com

 

Herança na prática

A herança foi o recurso mais esperado no Visual Basic. Note que estou usando o verbo no passado pois no VB.NET a herança chegou.

Se você já conhece o conceito de herança de outras linguagens (Java, por exemplo) sabe o quão poderoso pode ser este recurso, sabe também que ele deve ser usado com um bom planejamento e que tem suas limitações.

Se você não conhece e nunca teve contato com o conceito de herança antes, provavelmente deva estar curioso e ansioso para aprender o que é e como usar na prática herança.

Neste artigo vou lançar as bases para que você tenha conceitos básicos e sólidos sobre o que é a herança e como e quando usá-la na plataforma .NET.

Para acompanhar este artigo você precisa ter noções básicas sobre conceitos da programação orientada a objetos. Os artigos abaixo relacionados podem lhe ajudar neste quesito:

O VB 6 e a herança de interface

Embora a herança de implementação seja um novidade bem vinda no VB.NET no VB 6 você tinha o que chamamos de herança de interface. A herança de interface funciona assim :

·                            Você cria uma interface de um componente reutilizável definindo em um módulo de classe uma classe com as definições das propriedades sem nenhum código de implementação

·                            Para usar a interface definida acima em outra classe você deveria usar a palavra chave implements seguida do nome da interface

Vamos supor que você queira criar um objeto Pessoa que tenha todas as propriedades compartilhadas por gerentes e operários. Como já disse no VB6 você cria um módulo de classe com as definições das propriedades sem nenhum código implementado. Vou chamar esta classe de interface com o nome Pessoa. O código da interface é descrito abaixo:

Public Property Get nome() As String
End Property

Public Property Let nome(Nome As String)
End Property

Public Property Get endereco() As String
End Property

Public Property Let endereco(Endereco As String)
End Property

Public Function receberSalario() As Boolean
End Function

              

Para criar esta classe estando com o seu VB aberto em um projeto selecione no menu
Project a opção : Add Class Module

 

O código da classe Pessoa ao lado define a interface Pessoa
Note que não há código de implementação para nenhum método ou propriedade.

 

Obs:Tecnicamente, o VB não podia criar interfaces, mas você podia usar o
truque de criar um módulo de classe apenas com definições de propriedades
e métodos, e então implementá-los em outra classe.
Era apenas a criação de uma classe, sem nenhum código de
implementação dentro dela, assim ela era vista como uma interface

A interface Pessoa

 

O VB.NET e a herança de implementação

No VB .NET, você não tem que criar uma interface em separado, embora você até possa. Você pode criar uma classe com código de implementação e herdá-la em outra classe. Isto significa que você poderia adicionar o código para as propriedades Nome e Endereco e para o método receberSalario() em uma classe Pessoa. Então, as classes Gerente e Operario poderiam ambas herdar da da classe base Pessoa. Gerente e Operario teriam ambos acesso ao código interno à Pessoa, ou poderiam substituí-lo pelo seu próprio código se fosse preciso.

Uma coisa a observar é que no VB .NET, todas as classes são herdáveis por default. Isto inclui formulários, que são apenas mais um tipo de classe. Isto significa que você pode criar um novo formulário baseado em um já existente. Você verá um exemplo de herança de formulários mais adiante neste capítulo.

Embora o VB .NET possibilite a verdadeira herança de implementação, as interfaces não desapareceram. Na verdade, elas foram muito melhoradas no VB .NET; juntas, herança e interfaces lhe dão a possibilidade de usar polimorfismo.

Usando Herança

Vamos então ver na prática como funciona e como podemos usar herança no VB.NET. Eu vou usar SharpDevelop que teve sua versão 1.02 disponibilizada recentemente para criar as classes e o todo o código visto neste artigo. Só para lembrar, o SharpDevelop é uma ferramenta open-source (GPL) que você pode obter em: http://www.sharpdevelop.com/OpenSource/SD/Default.aspx

Após instalar o SharpDevelop , execute-o e crie um novo projeto escolhendo no Menu a opção File e a seguir New Combine; a seguir selecione Windows Application , informe um nome para o projeto na caixa Name e clique em Create, conforme figura a seguir:

image001.gif

Vamos agora criar uma classe chamada Forma. O objetivo de criarmos a classe Forma époder reutilizar seus métodos e propriedades usando herança.

Na classe Forma iremos definir duas propriedades :

·                            posX - define a posição X

·                            posY - define a posição Y

Uma propriedade nada mais é do que uma variável que está contida em uma classe e representa um atributo da classe.

Observe que as duas propriedades são definidas como do tipo Private, por que pelas regras de encapsulamento as propriedades são sempre privadas para uma classe. Com isto, o código que é executado fora da classe não é capaz de acessar as propriedades diretamente. Esta técnica faz com que a classe tenha o controle independente do restante do programa.

Como então ter acesso a estas propriedades? (Se você pensou nisto , boa pergunta garoto...)

Para termos realmente propriedades genuínas será preciso incluir um procedimento (um método especial) que nada mais é do que um método que permite que a propriedade seja iniciada e devolvida a partir dos objetos da classe. Fazemos isto usando as palavras get e set.

Suas características são:

Os procedimentos das propriedades são definidos como Public pois o código que é executado fora da classe deve sre capaz de chamar o procedimento.

- A palavra-chave Property identifica este método especial como um procedimento da propriedade.

- Get/End Get é o procedimento da propriedade que devolve o valor da propriedade armazenado na propriedade

- Set/End Set é o procedimento da propriedade que atribui um valor recebido pelo comando Set para a área de armazenamento da propriedade

- Cada procedimento da propriedade é um método da classe e permitem que seus programas possam obter e atribuir valores à propriedade a qualquer momento. (os valores iniciais somente podem ser atribuídos às propriedades na hora de criar um objeto da classe. Para fazer isto usamos um método especial chamado construtor)

Public Class Forma

Private posX As Integer
Private posY As Integer

Public Property posicaoX() As Integer
 Get
    return posX
 End Get
 Set(ByVal valor As Integer)
    posX=valor
 End Set
End Property

Public Property posicaoY() As Integer
  Get
     return posY
  End Get
  Set(ByVal valor As Integer)
     posY=valor
  End Set
End Property

End Class

Agora eu vou criar mais duas classes: a classe Retangulo e a classe Circulo. Estas classes irão usar herança para herdar as propriedades e métodos (se houver) da classe Forma. O código da classe Retangulo e da classe Círculo é dado a seguir:

Public Class Retangulo
         Inherits Forma

Private l As Integer
Private h As Integer

Public Property largura As Integer
   Get
      return l
    End Get
    Set(ByVal valor As Integer)
        l=valor
    End Set
End Property

Public Property altura As Integer
   Get
     return h
   End Get
   Set(ByVal valor As Integer)
      h=valor
    End Set
End Property
End Class

 

Public Class Circulo
         Inherits Forma

Private d As Integer

Public Property diametro As Integer
   Get
       return d
   End Get
   Set(ByVal valor As Integer)
           d=valor
    End Set
End Property

End Class

A cláusula Inherits Forma usada na classe Retangulo e Circulo faz com que estas duas classes herdem as propriedades e métodos da classe Forma.

Para testar e verificar a herança vou incluir um botão no formulário e no evento Click do botão inserir o seguinte código :

Private Sub Button1Click(sender As System.Object, e As System.EventArgs)

Dim f As New Forma()
Dim r As New Retangulo()
Dim c as new circulo()

f.PosicaoX=10
f.PosicaoY=20

r.PosicaoX=15
r.PosicaoY=30

r.altura=25
r.largura=40

c.posicaoX = 15
c.posicaoY = 25

c.diametro = 5

messageBox.Show(f.ToString() & " x: " & r.PosicaoX & " y: " & r.PosicaoY & " l: " & r.largura & " h: " & r.altura)
messageBox.Show(c.ToString() & " x: " & c.PosicaoX & " y: " & c.PosicaoY & " d: " & c.diametro)

End Sub

Vamos entender o que foi feito neste código :

Dim f As New Forma()
Dim r As New Retangulo()
Dim c as new circulo()
                                                 

Aqui estou criando três objetos : f do tipo Forma , r do tipo Retangulo e c do tipo Circulo

Lembre-se que Forma , Retangulo e Circulo são classes que definimos.

f , r e c são nomes dos objetos que estamos criando a partir das classes.

(lembre-se que uma classe pode ser vista como um modelo para um objeto)

Para usar os métodos e propriedades da classe você precisa criar um objeto da classe.

r.PosicaoX=15
r.PosicaoY=30

r.altura=25
r.largura=40


c.posicaoX = 15
c.posicaoY = 25

c.diametro = 5

Estas linhas de código atribuem valores às propriedades dos objetos. Observe que o objeto r que foi instanciado a partir da classe Retangulo herdou as propriedades posicaoX e posicaoY da classe Forma

Objeto c instanciado a partir da classe Circulo somente tinha a propriedade diametro mas herdou da Classe Forma as propriedades posicaoX e posicaoY.

messageBox.Show(f.ToString() & " x: " & r.PosicaoX & " y: " & r.PosicaoY & " l: " & r.largura & " h: " & r.altura)
messageBox.Show(c.ToString() & " x: " & c.PosicaoX & " y: " & c.PosicaoY & " d: " & c.diametro)

O código acima apenas exibe os valores atribuídos aos objetos.

Vamos avançar um pouco nos conceitos OOP. Vamos ver como funciona o conceito de polimorfismo.

Temos a classe Forma e as classes Retangulo e Circulo que herdam da classe Forma. A classe Forma é a classe Pai ou classe base e as classes Retangulo e Circulo são as classes filhas ou derivadas.

Vamos incluir um método nas classes que permita desenha as formas das figuras na tela. Vamos então incluir o método desenhar nestas classes; mas antes um detalhe: você não desenha um circulo da mesma maneira que desenha um retângulo, certo?

Entra em cena então o polimorfismo. Polimorfismo nada mais é do que a habilidade de criar objetos que realizam as mesmas funções de maneiras diferentes.

É isto justamente o que vamos fazer aqui: desenhar figuras usando o mesmo método de maneira diferentes.

Como a classe Forma é a classe Pai, é por ela que vamos começar fazendo as alterações necessárias para implementar o que desejamos.

Dê uma boa olhada no novo código da classe Forma e veja o código em azul que foi acrescido ao código inicial.

Public MustInherit Class Forma

Private posX As Integer
Private posY As Integer

   Sub New(ByVal x As Integer, ByVal y as Integer)
          posx=x
          posy=y
   End Sub 

Public Property posicaoX() As Integer
 Get
    return posX
 End Get
 Set(ByVal valor As Integer)
    posX=valor
 End Set
End Property

Public Property posicaoY() As Integer
  Get
     return posY
  End Get
  Set(ByVal valor As Integer)
     posY=valor
  End Set
End Property

MustOverride Sub desenhar(ByVal g As Graphics)

End Class

Na primeira linha incluímos a palavra MustInherit :

Public MustInherit Class Forma

MustInherit é um modificador que faz com que uma classe seja destinada apenas a servir como base para a criação de outras classes. Desta forma não é possível criar instâncias diretas desta classe. (Chamamos isto de classe abstrata em Java)

Em outras palavras: nenhum programa poderá criar um objeto Forma , ao invés disto , o programa terá que herdar a classe Forma e criar os objetos a partir dela.

Por quê fizemos isto?

Dê uma olhada na classe forma. Ela é muito genérica e nem possui um método desenhar definido apenas declarado. A única razão de termos criado a classe Forma é fornecer um local de armazenamento para as propriedades e métodos que são comuns para todas as formas , como retângulos e círculos.

A próxima diferença é que criamos um construtor para a classe Forma:

 Sub New(ByVal x As Integer, ByVal y as Integer)
          posx=x
          posy=y
 End Sub 

Com isto podemos iniciar a classe forma da seguinte maneira: Dim r = New Forma(2,2)

A última alteração foi a inclusão da linha de código:

MustOverride Sub desenhar(ByVal g As Graphics)

O modificador MustOverride exige uma classe herdada para sobrepor a propriedade ou o método.

Cada classe que usar a classe Forma como base vai ter que definir um método desenhar de acordo com a declaração feita na classe Forma ,i.e, tendo a mesma assinatura.

Resumindo:

·                            A classe Forma é uma classe abstrata e não pode ser instanciada

·                            A classe Forma possui um construtor que recebe dois parâmetros x e y inteiros

·                            A classe Forma declara o método desenhar(ByVal g As Graphics) que deverá ser implementado por qualquer classe que herdar da classe Forma.