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 |
| |||
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:
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 |
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 |
|
Public Class Circulo |
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) |
Vamos entender o que foi feito neste código :
Dim f As New Forma() |
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 |
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) | |
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 Sub New(ByVal x As Integer, ByVal y as Integer) MustOverride Sub desenhar(ByVal g As Graphics) |
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) 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.