agosto 04, 2006

EJEMPLO 2. CLASES ABSTRACTAS

EN ESTE PROGRAMA ESTAMOS IMPLEMENTANDO CLASES ABSTRACTAS.
CONTIENE 3 CLASES Y UN MODULO PRINCIPAL

Public MustInherit Class poligono
Protected m_x, m_y As Double
Public Property x() As Double
Get
Return m_x
End Get
Set(ByVal Value As Double)
m_x = Value
End Set
End Property
Public Property y() As Double
Get
Return m_y
End Get
Set(ByVal Value As Double)
m_y = Value
End Set
End Property

Public MustOverride Function calcular() As Double

End Class


Public Class cuadrado
Inherits poligono

Public Overrides Function calcular() As Double
Return m_x * m_y
End Function

Public Sub New(Optional ByVal x As Double = 0, Optional ByVal y As Double = 0)
m_x = x
m_y = y
End Sub
End Class


Public Class triangulo
Inherits poligono
Public Overrides Function calcular() As Double
Return (x * y) / 2
End Function
Public Sub New(Optional ByVal x As Double = 0, Optional ByVal y As Double = 0)
m_x = x
m_y = y
End Sub

End Class

' MODULO PRINCIPAL

Module Module1
Sub Main
Dim pol As poligono = New cuadrado (10,5)
MSGBOX(CStr(pol.calcular())

pol = New triangulo (10,10)
MSGBOX(CStr(pol.calcular())
End sub
End Module

Ejemplo de una clase abstracta

EL SIGUIENTE PROGRAMA ES UNA APLICACION DE WINDOWS.
CONTIENE:
TRES CLASES, LAS CUALES ESTAN DIVIDIDAS EN DOS BLOQUES UNO ACTIVO Y OTRO EN COMENTARIOS. EN EL BLOQUE DE COMENTARIOS SE ESTA IMPLEMENTANDO LAS CLASES ABSTRACTAS, EN EL QUE NO TIENE COMENTARIOS SOLO SE LE ESTA APLICANDO HERENCIA.

Public Class Cuenta
Protected m_balance As Decimal
Public Property balance() As Decimal
Get
Return m_balance
End Get
Set(ByVal Value As Decimal)
m_balance = Value
End Set
End Property


Public Sub New(Optional ByVal iniciobalance As Decimal = 0)
m_balance = iniciobalance
End Sub
End Class
'**********************************************************************
'Public MustInherit Class Cuenta
' Protected m_balance As Decimal
' Public Property balance() As Decimal
' Get
' Return m_balance
' End Get
' Set(ByVal Value As Decimal)
' m_balance = Value
' End Set
' End Property

' Public MustOverride Sub CierredelMes()
' Public Sub New(Optional ByVal iniciobalance As Decimal = 0)
' m_balance = iniciobalance
' End Sub
'End Class


Public Class cuentadeahorro
Inherits Cuenta
'interes compartido, por default es 0.5% al mes
'The Shared keyword indicates that one or more declared programming elements are shared. Shared elements are not associated with a specific instance of a class or structure. You can access them by qualifying them either with the class or structure name, or with the variable name of a specific instance of the class or structure.

Protected Shared s_interes As Decimal = CDec(0.005)

Public Shared Property interes() As Decimal
Get
Return s_interes
End Get
Set(ByVal Value As Decimal)
s_interes = Value
End Set
End Property

Public Sub New(Optional ByVal iniciobalance As Decimal = 0)
MyBase.New(iniciobalance)
End Sub

Public Sub CierredelMes()
If m_balance < 0 Then
m_balance -= 25
Else
m_balance *= 1 + s_interes
End If
End Sub
End Class
'**********************************************************************
'Public Class cuentadeahorro
' Inherits Cuenta
' Protected Shared s_interes As Decimal = CDec(0.005)

' Public Shared Property interes() As Decimal
' Get
' Return s_interes
' End Get
' Set(ByVal Value As Decimal)
' s_interes = Value
' End Set
' End Property

' Public Sub New(Optional ByVal iniciobalance As Decimal = 0)
' MyBase.New(iniciobalance)
' End Sub

' Public Overrides Sub CierredelMes()
' If m_balance < 0 Then
' m_balance -= 25
' Else
' m_balance *= 1 + s_interes
' End If
' End Sub
'End Class

Public Class CuentadeCheques
Inherits Cuenta
Public Sub CierredelMes()
If m_balance < 0 Then
m_balance -= 25
ElseIf m_balance < 2500 Then
m_balance -= 4
End If
End Sub

Public Sub New(Optional ByVal iniciobalance As Decimal = 0)
m_balance = iniciobalance
End Sub
End Class
'**********************************************************************
'Public Class CuentadeCheques
' Inherits Cuenta
' Public Overrides Sub CierredelMes()
' If m_balance < 0 Then
' m_balance -= 25
' ElseIf m_balance < 2500 Then
' m_balance -= 4
' End If
' End Sub

' Public Sub New(Optional ByVal iniciobalance As Decimal = 0)
' m_balance = iniciobalance
' End Sub
'End Class

CODIGO DEL BOTON DE LA FORMA:

Dim cc As CuentadeCheques = New CuentadeCheques(CDec(txtinibalanceCC.Text))
cc.CierredelMes()
txtbalanceCC.Text = cc.balance

Dim ca As cuentadeahorro = New cuentadeahorro(CDec(txtIniBalanceCA.Text))
ca.CierredelMes()
txtbalanceCA.Text = ca.balance
'**********************************************************************
'Dim c As Cuenta = New CuentadeCheques(CDec(txtinibalanceCC.Text))
'c.CierredelMes()
'txtbalanceCC.Text = "$ " & c.balance

'c = New cuentadeahorro(CDec(txtIniBalanceCA.Text))
'c.CierredelMes()
'txtbalanceCA.Text = "$ " & c.balance

Funciones Virtuales-Overridable

FUNCIONES VIRTUALES
Las funciones virtuales son usadas principalmente en lenguajes en C++ o C#, la implementación de funciones virtuales en Visual Basic .NET es a través de la sobre escritura de métodos o propiedades o subrutinas.

Public MustInherit Class animal

Public Overridable Function mensaje()
MsgBox("no se que tipo de bestia soy")
End Function

Public Overridable ReadOnly Property msg1() As String
Get
Console.WriteLine("No se que tipo de animal soy")
End Get
End Property

Public Overridable Sub quetipo()
MsgBox("Que tipo soy")
End Sub

Public MustOverride Function mensaje2()


End Class

Public Class humano
Inherits animal
Public Overrides Function mensaje()
MsgBox("se que soy humano")
End Function

Public Overrides ReadOnly Property msg1() As String
Get

Return "soy un humano en la propiedad"
End Get
End Property
Public Overrides Sub quetipo()
MsgBox("soy del tipo de humano")
End Sub

Public Overrides Function mensaje2()
MsgBox("Este es un mensaje de los humanos")
End Function

End Class

Public Class perro
Inherits animal
Public Overrides Function mensaje()
MsgBox("soy un perro")
End Function
Public Overrides ReadOnly Property msg1() As String
Get
Return "soy un tipo de perro"
End Get
End Property

Public Overrides Sub quetipo()
MsgBox("soy del tipo perro")
End Sub

Public Overrides Function mensaje2()
MsgBox("Este es un mensaje de los perros")
End Function
End Class



La idea detrás del polimorfismo es que a un grupo de objetos heterogéneos (por ejemplo, manzanas, naranjas, plátanos) pueda hacer que se vean como homogéneo (por ejemplo, frutas), pero puedan ser diferenciadas basados en su propio tipo especifico al ejecutarse.


Module Module1
Sub Main()
'Console.WriteLine("Vamos a mostrar a un humano")
Dim animal1 As animal = New humano
'animal1.mensaje()
'Console.WriteLine("Vamos a mostrar a un perro")
Dim animal2 As animal = New perro
'animal2.mensaje()
'MsgBox(animal1.msg1)
'animal1.quetipo()
'animal2.quetipo()

animal1.mensaje2()
animal2.mensaje2()
End Sub
End Module


La palabra New introduce una Nueva cláusula (punto, condición), la cual crea un nuevo objeto de la instancia. La cláusula New debe de especificar una clase definida de la cual la instancia pueda ser creada. Podemos usar New en una declaración de un enunciado o en un enunciado de asignación. Cuando el enunciado es ejecutado, este llama al constructor para la clase especifica, pasando cualquier argumento que hayas suplido.

Since arrays are classes, New can create a new array instance:
Dim MyArray As Integer()
MyArray = New Integer() {0, 1, 2, 3}


Clases Abstractas
Habra algunos casos en las cuales la clase base de una herencia gerarquica ocupe un metodo sobrescrito *(overridable ), pero la clase por si misma no puede proveer ninguna implementacion para le método. En este caso lo que necesitamos es una forma de forzar a la clase derivada sobre escribir el Método.
<<>>


Los métodos declarados como MustOverride no deben de tener un cuerpo, y no deben de terminar en End Sub ó End Function. Ademas una clase que contiene uno o mas métodos de este tipo (conocidos como métodos abstractos) deben de ser declarados como MustInherits aun así que no tenga métodos abstractos, solo para prevenir que algunos clientes creen instancias de este tipo.

Public MustInherits Class Account
Protected m_balance as Decimal
‘el resto del código omitido
Public MustOverrides Sub CloseMonth()
End Class

Esto significa que podemos ahora tratar cualquier método o subrutina gericamente. En general se puede tener herencia jerárquica con múltiples niveles de clases abstractas, pero esto es inusual. En caso de que no pueda omitirse, todas las clases derivadas deben de implementar en todos los métodos declarados como MustOverride de todas las clases abstractas en sus ancestros de los cuales heredaron, o convertirse a si mismo abstractos (usando MustInherit).

Bibliografía
Virtual functions
Foundations of OOP Using dot NET 2.0 Patterns.pdf p.13
Visual Basic .NET by example p.327-328

Polimorfismo

Polimorfismo viene de la raíz del Griego polu (muchos) y morphe (forma), y significa en términos de computación una entidad que puede tener múltiples formas o comportamiento diferente. En el caso especifico de herencia significa que las clases derivadas pueden tener comportamientos diferentes para el mismo método.
Ejemplo de un metodo sencillo

Public Class Empleado
Inherits Person
Protected m_salario as Decimal
‘El resto del código omitido
Public Function PagoMensual() as Decimal
Return m_salario / 12
End Function

Public Class Empleado
Inherits Person
Protected m_salario as Decimal
‘El resto del codigo omitido
Public Overridable Function PagoMensual() As Decimal
Return m_salario/12
End Function
End Class

Sobre escribiendo el metodo en una clase derivada

Public Class EmpleadoVentas
Inherits Empleado
Protected m_bonoExtra as Decimal
‘el resto del codigo omitido
Public Overrides Function PagoMensual() as Decimal
Return (m_salario / 12) * (1+ m_bonoExtra)’Es el porcentaje del bono
End Function
End Class

Public Class Gerente
Inherits Empleado
Protected m_bono as Decimal
‘El resto del codigo omitido
Public Overrides Function PagoMensual() as Decimal
Return MyBase.PagoMensual() * m_bono
End Function
End Class

Como podemos ver de este ejemplo, usamos Overrides para los métodos en las clases derivadas para especificar que vamos a sobreescribir el comportamiento de un método declarado en la clase base. Podemos acceder de un método que fue Overridable (se puede sobre escribir) en una clase derivada y utilizar la implementación del método utilizando la palabra MyBase.

La razón por la que el polimorfismo es una técnica tan popular en la programación orientada a objetos es el hecho de que el compilador conoce que tipo de objeto esta tratando. Aun así de que el objeto se use a través de una referencia de su clase base.

Es importante que entendamos que hay una diferencia fundamental entre el concepto de sobrecargo (overloaded) en métodos y propiedades y el concepto de polimorfismo Sobre escritura de métodos y propiedades (overridable methods and properties). Sobrecargo (Overloading) significa tener mas de un método con el mismo nombre, pero un listado diferente de argumentos (numero, orden o tipo), en la misma clase o en combinación de las clases base o derivadas. Sobrescribir (Overriding) un método significa tener un método con el mismo nombre y los mismos argumentos en una clase derivada, un metodo que sera llamado automáticamente cuando un objeto de la clase derivada es el objetivo de la invocación. Cuando un método sobrecargado es llamado, esta determinado por el que lo llama. Cuando se llama a un método Sobrescrito (Overridden), el programa decodifica la implementación del método a llamar (la clase base o la clase derivada) dependiendo del tipo.


Un comportamiento existente de una clase base puede ser completamente redefinido o sobreescrito en una clase derivada, pero solo si el programador de la clase base lo hace permisible. Para que un metodo pueda ser sobrescrito (overridden), debe de ser declarado usando el modificador Overridable.