VB 2005 - Polimorfismo com classes Abstratas
Vamos supor que você precisa desenvolver um projeto para calculo de áreas e que de início deverá calcular a área do retângulo, do triângulo e do quadrado.
Como um bom conhecedor dos conceitos da programação orientada a objetos(poo) você cria um novo projeto no Visual Basic 2005 Express e imediatamente no menu Project inclui uma classe usando a opção Add Class dando ao arquivo o nome Areas.vb.
Nota: Para saber mais sobre conceitos da programação orientada a objetos leia o meu artigo: Revisitando conceitos OOP
A seguir você decide, baseado na sua experiência na poo, criar um classe chamada Retangulo com as seguintes características:
O código da classe esta listado abaixo:
Public Class Areas Public Class Retangulo Private _altura As Double Private _base As Double Public Sub New(ByVal h As Double, Bl base As Double) Me.Altura = h Me.Base = b End Sub Public Property Altura() As Double Get Return _altura End Get Set(ByVal value As Double) _altura = value End Set End Property Public Property Base() As Double Get Return _base End Get Set(ByVal value As Double) _base = value End Set End Property Public Function getArea() As Double Return _altura * _base End Function End Class End Class |
Muito bem, você já pode obter a área do retângulo usando o método getArea() e definindo as propriedades Altura e Base. Até aqui nada de especial.
Você parte então todo entusiasmado para criar sua segunda classe , a classe Triangulo, que irá calcular a área do triângulo. O código usado esta mostrado a seguir:
Public Class Triangulo Private _altura As Double Private _base As Double Public Sub New(ByVal base As Double, ByVal altura As Double) Me.Altura = h Me.Base = b End Sub Public Property Altura() As Double Get Return _altura End Get Set(ByVal value As Double) _altura = value End Set End Property Public Property Base() As Double Get Return _base End Get Set(ByVal value As Double) _base = value End Set End Property Public Function getArea() As Double Return ( _base * _altura) / 2 End Function End Class |
Para encerrar você cria a classe Quadrado contendo uma propriedade , o construtor e o método getArea(), conforme código abaixo:
Public Class Quadrado Private _lado As Double Public Sub New(ByVal lado As Double) Me.Lado = lado End Sub Public Property Lado() As Double Get Return _lado End Get Set(ByVal value As Double) _lado = value End Set End Property Public Function getArea() As Double Return _lado * _lado End Function End Class |
Após terminar as classes você implementou em um formulário , form1.vb do projeto , o código para fazer os testes.
A interface criada usou apenas três botões conforme figura abaixo:
O código usado no formulário é mostrado a seguir: |
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim r As New Areas.Retangulo(10, 20) MsgBox("Area do retangulo de base=10 e altura=20 : " & r.GetArea()) End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Dim r As New Areas.Triangulo(10, 20) MsgBox("Area do triangulo de base=10 e altura=20 : " & r.getArea()) End Sub Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click Dim r As New Areas.Quadrado(10) MsgBox("Area do quadrado de lado 10 : " & r.getArea()) End Sub |
Após terminar todo este trabalho você analisou melhor o seu código e percebeu o seguinte:
Atento a estes detalhes você se convenceu que pode otimizar o código usado. Você então resolveu aplicar seus conhecimentos avançados de orientação a objeto e usar o conceito de classes abstratas.
Nota: Veja mais sobre este assunto no meu artigo : Classes Abstratas
No VB.NET uma classe é definida como abstrata através do uso do modificador MustInherit. Então para criar uma classe abstrata do VB.NET você precisa preceder a palavra chave Class com o modificador MustInherit .
Um método que possui somente a assinatura(declaração) sem qualquer implementação pode também ser chamado de um método abstrato. Para declarar um método como abstrato no VB .NET você precisa usar o modificador MustOverride pois os métodos abstratos precisam ser sobrescritos e implementados nas classes filhas com a mesma assinatura com o qual foi definido na classe pai.
Uma classe precisa ser definida como abstrata se possuir pelo menos um método abstrato; ela pode no entanto conter diversos métodos não abstratos. Lembre-se que você não pode instanciar uma classe Abstrata como faz com uma classe comum visto que ela não esta totalmente implementada.
Com base nestes conceitos você definiu uma classe Forma com o seguinte código:
Public MustInherit Class Forma Private _x As Double Private _y As Double Public Sub New() End Sub Public Sub New(ByVal valor As Double) Me.X = valor End Sub Public Sub New(ByVal valor1 As Double, ByVal valor2 As Double) Me.X = valor1 Me.Y = valor2 End Sub Public Property X() As Double Get Return _x End Get Set(ByVal value As Double) _x = value End Set End Property Public Property Y() As Double Get Return _y End Get Set(ByVal value As Double) _y = value End Set End Property Public MustOverride Function GetArea() As Double End Class |
A classe Forma é uma classe abstrata(MustInherit) e possui as seguintes características:
Note que o método foi definido sem qualquer implementação e deverá ser sobrescrito nas classes filhas.
Agora podemos redefinir a classe Retangulo que deverá herdar da classe Forma. Ao final a classe deverá ficar assim:
Public Class Retangulo Inherits Forma Public Sub New(ByVal lado As Double, ByVal base As Double) MyBase.New(lado, base) End Sub Public Overrides Function getArea() As Double Return Me.X * Me.Y End Function End Class |
A nova classe Retangulo agora possui um construtor contendo a
seguinte instrução: MyBase.New(lado, base)
Esta instrução chama o construtor da super classe (a classe Forma)
A nova classe Retangulo sobrescreve o método getArea() e foi implementando com a mesma assinatura da classe abstrata(Forma) e retornando o valor da área do retângulo.
Vamos fazer o mesmo com a classe Triangulo que deverá ficar com o seguinte código:
Public Class Triangulo Inherits Forma Public Sub New(ByVal base As Double, ByVal altura As Double) MyBase.New(base, altura) End Sub Public Overrides Function getArea() As Double Return (Me.X * Me.Y) / 2 End Function End Class |
A nova classe Triangulo também possui um construtor que chama o construtor da classe Pai e implementa o método getArea() com a mesma assinatura da classe abstrata Forma, mas retornando o valor da área do triângulo.
A classe Quadrado também deve ser alterada. Veja como ficou o seu código:
Public Class Quadrado Inherits Forma Public Sub New(ByVal lado As Double) MyBase.New(lado) End Sub Public Overrides Function getArea() As Double Return Me.X * Me.X End Function End Class |
Na classe Quadrado temos o método getArea() também sobrescrevendo o método definido na classe Pai e definido com a mesma assinatura mas retornando o valor da área do quadrado.
Agora só falta alterar o código do formulário para testar cada uma das classes que agora herdam da classe abstrata Forma. O código deverá ser alterado conforme abaixo:
Public Class Form1 Dim f As Areas.Forma = Nothing Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click f = New Areas.Retangulo(10, 20) MsgBox("Area do retangulo de base=10 e altura=20 : " & f.getArea()) End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click f = New Areas.Triangulo(10, 20) MsgBox("Area do triangulo de base=10 e altura=20 : " & f.getArea()) End Sub Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click f = New Areas.Quadrado(10) MsgBox("Area do quadrado de lado 10 : " & f.getArea()) End Sub End Class |
Uma observação importante que deve ser feita ao código acima é que agora estamos sempre usando a mesma variável(variável de referência e não um objeto concreto) para tratar as instâncias de todas as classes filhas : Retangulo, Triangulo e Quadrado ; a variável f .
Note também que a mesma variável f agora é usada para chamar o mesmo método getArea() obtendo resultado diferentes.
Quando você usa o mesmo método com a mesma assinatura e com diferentes implementações e diferentes execuções obtendo resultados diferentes você tem o que chamamos de Polimorfismo.
Definição
Acadêmica: O termo polimorfismo, etimologicamente, quer dizer "várias formas"; todavia, na Informática, e em particular no universo da OOP, é definido como sendo um código que possui "vários comportamentos" ou que produz "vários comportamentos"; em outras palavras, é um código que pode ser aplicado à várias classes de objetos. De maneira prática isto quer dizer que a operação em questão mantém seu comportamento transparente para quaisquer tipos de argumentos; isto é, a mesma mensagem é enviada a objetos de classes distintas e eles poderão reagir de maneiras diferentes. Um método polimórfico é aquele que pode ser aplicado à várias classes de objetos sem que haja qualquer inconveniente. Nelson Abu Sanra Rahal Júnior Mestre em Ciência da Computação (UFSC), Doutorando em Ciência da Computação (UFSC) |
Outra definição: |
Polimorfismo,
originário do grego, significa "muitas formas"
(poli = muitas, morphos = formas). Ele permite
que referências de tipos de classes mais abstratas
representem o comportamento das classes concretas que
referenciam. Assim, um mesmo método pode apresentar
várias formas, de acordo com seu contexto. O
polimorfismo é importante pois permite que a semântica
de uma interface seja efetivamente separada da
implementação que a representa. http://pt.wikipedia.org/wiki/Polimorfismo |
Então, sem querer querendo, você acabou usando um recurso muito valioso da programação orientada a objetos: a reutilização de código com encapsulamento e herança.
Até o próximo artigo...
Referências:
José Carlos Macoratti