{ WillyXoft .NET }

Blog de Willy Mejía sobre Microsoft .NET Framework y temas relacionados...

<August 2008>
SuMoTuWeThFrSa
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456


Navigation

e-Grupos / Foros

Web/Blog Amigos

INETA & MUGs

Subscriptions

News

Post Categories

Article Categories



POO con Visual Basic .NET Parte 3 Rated Good [4 out of 5].

Programación Orientada a Objetos con Visual Basic .NET
Parte III

Por Willy Mejía [WillyXoft]

Heredando

La Herencia es una de las características más importantes en la POO porque  permite que una clase herede los atributos y métodos de otra clase, lo que garantiza la reutilización de código.

Con la herencia todas las clases están clasificadas según una jerarquía. Cada clase tiene una clase base o superclase, ésto es de jerarquía superior, y puede tener una o más clases derivadas o subclases, de inferior jerarquía. Las clases que están en la parte inferior de una jerarquía heredan de las clases que están en la parte superior de su jerarquía.

La herencia implica que las subclases disponen de todos los miembros públicos (métodos y propiedades) de su superclase. Lo cual permite extender la funcionalidad de una clase añadiendo sus propios atributos y métodos o incluso alterando el comportamiento heredado. De este modo se pueden crear objetos especializados en base a otros, tal y como se observa en la vida real.

La herencia hace posible la reutilizacion de componentes, que es una de las principales razones para utilizar el paradigma de la POO, la otra es que facilita el entendimiento (legibilidad) y mantenimiento del código implementado.

Con la Herencia puede definir una clase común como la clase base o madre (o padre según lo prefiera) para otras clases llamadas clases derivadas o hijas, las cuales serían versiones especializadas de la primera. A su vez, los miembros heredados por una clase derivada pueden ser heredados por más clases hijas de ella, propagando la herencia.

Por ejemplo,  toda clase en el .NET Framework es una subclase de la clase base llamada System.Object, de la cual heredan sus propiedades y métodos públicos, entre ellos el el método ToString(). De modo que si creamos una clase llamada Cliente la cual no declare ni implemente método alguno, aún así podríamos invocar el método ToString():

Class Cliente
End Class 
Cliente.ToString()

No obstante podemos sobre-escribir el comportamiento de dicho metodo utilizando la palabra clave Overrides:

Public Overrides Function ToString() As String
    Return mNombre
End Public

Esta operación se puede realizar con cualquier método heredado, siempre y cuando el método de la clase base lo permita por medio de la palabra clave Overridable. Pero ésto lo abodaremos más adelante en Polimorfismo.

Para poder definir la herencia directa hacia una clase en particular se utiliza la palabra clave Inherits. De modo que teniendo una clase (A) podemos escribir otra clase (B) que herede su implementación de la siguiente manera:

Class A
End Class 

Class B
Inherits A
End Class

Así por ejemplo, para crear una clase que herede de Cliente, escribimos:

Public Class ClienteFrecuente
Inherits Cliente
    Public Sub New()
        MyBase.New()
    End Sub
    ' Implementación especializada de la clase...
End Class

El constructor de una clase Derivada llama de manera implícita al constructor de su clase Base. Pero se puede utilizar la palabra clave MyBase para invocar cualquier miembro público de la clase Base, en éste caso al constructor de la clase base Cliente, de manera explícita.

Por otro lado, puede utilizar la palabra clave MyClass permite llamar a un método remplazable (Overridable) implementado en la clase y asegurarse de que se llama a la implementación del método en esta clase y no a la de un método reemplazado en una clase derivada. Para un mayor entendimiento vuelva a leer este párrafo después de leer sobre Polimorfismo más adelante.

Cuando utilizar la herencia

Puede realizar herencia de clases jerarquizada según la necesidad de especialización requerida, no obstante se recomienda no ir mas alla de cuatro niveles. Por otro lado debe tener claro cuando no utilizar Herencia.

Los principales usos de la Herencia son cuando:

  1. Tiene objetos de diferentes tipos con funcionalidad similar.
  2. Tiene un conjunto de procesamientos a ser realizados por un conjunto de objetos.

Pero no debería utilizar Herencia cuando:

  • Sólo necesite una función de la clase base en su clase.
  • Si necesita sobre-escribir todos los métodos de la clase base -en ese caso mejor emplee Interfaces (ver más adelante).
  • La semantica de la herencia (o relación) entre clases no es muy clara.

El .NET Framework sólo permite la herencia simple entre clases, es decir que una clase Derivada sólo puede tener una sóla clase Base, pero si permite la herencia múltiple de Interfaces por medio de la implementación obligatoria de los miembros declarados en las Interfaces.

Una Interfaz es un tipo especial parecido una Clase, con la salvedad que sólo declara miembros públicos pero sin implementar código dentro de los mismos. Por lo que lo único que hereda es la obligación de implementar el código de dichos mimbros.

Para heredar la declaración de los miembros de una Interface se emplea la palabra clave Implement.

Interface IEjemplo
    Sub PorImplemetar()
End Interface

Class Implementadora
Inherits ClaseBase
Implements IEjemplo
    Public Sub PorImplementar() Implements IEjemplo.PorImplementar
        ' Código de implementación...
    End Sub
End Class

Dado que las Interfaces no heredan implementación de código, pocos ven la ventaja de utilizarlas. No obstante son muy útiles por diversas razones entre las cuales podemos citar la especificación de métodos y propiedades bajo contrato, de manera que estarémos seguros que todas las clases derivadas contarán con algúnos métodos o propiedades que pueden ser invocados con seguridad.

Para mayor información léa: Cuándo utilizar la herencia.

Encapsulando

La Encapsulacion es "referenciada" como el ocultamiento de datos. Para limplementarla utilizamos modificadores de acceso que son palabras clave que se utilizan para declarar o especificar el nivel de accesibilidad o "visibilidad" que tiene un miembro o un tipo. Cuando se permite el acceso a un miembro, se dice que éste es accesible o visible. De lo contrario, es inaccesible u oculto.

En VB.NET se manejan cuatro modificadores de acceso y cinco niveles de accesibilidad. Los modificadores de acceso son: Private, Protected, Friend y Public,  mientras que los niveles de accesibilidad, del más al menos restrictivo, són:

  • Private: Corresponde al nivel de acceso más restrictivo. Los miembros privados sólo son accesibles dentro del cuerpo de la clase o la estructura en la cual se declaran.
  • Protected: Los miembros protegidos son accesible desde dentro de la clase en la que se ha declarado, y desde dentro de cualquier clase derivada de la clase que declaró este miembro. Una clase derivada puede obtener acceso a un miembro Protected, siempre que el miembro no sea un miembro de una instancia o el acceso se realice a través de una instancia de la clase derivada.
    Nota: Este tipo de accesibilidad no puede ser utilizado en estructuras.
  • Friend: Los miembros de tipo "amigo" o interno sólo son accesibles dentro de archivos del mismo ensamblado. Desde el punto del IDE se dice que su accesibilidad es a nivel de proyecto, ya que por cada proyecto se genera un sólo ensamblado.
  • Protected Friend: Es una combinación de los dos anteriores, por lo que el acceso está limitado al proyecto actual o a los tipos derivados de la clase.
    Nota: Es la única combinación de modificadores de acceso permitida y no puede ser utilizada en estructuras.
  • Public: Corresponde al nivel de acceso menos restrictivo. No existen restricciones en el acceso a miembros públicos.

Los niveles de acceso privado (Private) y protegido (Protected) aseguran la encapsulación, ya que ocultan o hacen inccesibles a los miembros desde el exterior de la clase. Por ello los campos (variables) son declarados con éstos modificadores de acceso, mientras los miembros que alteran su valor: propiedades, procedimientos y funciones, son declarados como públicos (Public).

El uso habitual del acceso de tipo Friend (y Protected-Friend) se da en el desarrollo basado en componentes, ya que permite a un grupo de componentes el cooperar de manera privada sin estar expuesto al resto de la aplicación.

Si no se especifica ningún modificador de acceso en una declaración de miembro, se utiliza el nivel de acceso predeterminado para el tipo de miembro. El nivel de acceso predeterminados para las variables es Private, mientras que para las propiedades, procedimientos y funciones es Public. No obstante es altamente recomendable el siempre especificar de manera explícita el nivel de acceso de los diferentes miembros.

Veamos un ejemplo:

'Project One
    Class A
        Private i As Integer
        Protected l As Integer
        Friend j As Integer
        Protected Friend m As Integer
        Public k As Integer
    End Class
    Class B
        'Puede acceder a: j,k,m
    End Class
    Class C 
    Inherits A 'Derivada de A
        'Puede acceder a: j,k,l,m
    End Class
'Project Y
    Class D
    Inherits A 'Derivada de A
        'Puede acceder a: k,l,m
    
    Class E
        'Sólo puede acceder a k 
    End Class

Polimorfismo

El polimorfismo proporciona la capacidad de variar la implementación de un método remplazable (o sobre-escribible), de modo que el mismo método base puede realizar diferentes acciones, dependiendo de la instancia que invoque el método en tiempo de ejecución. En VB6 se empleaban las interfaces, mismas que aún pueden seguir utilizándose en Visual Basic .NET. Mas ahora también podemos implementar el Polimorfismo mediante Herencia, para ello el método remplazable en la clase Base deberá estar calificado con la palabra clave Overridable, y el método que lo remplaza en la clase derivada deberá estar calificado con la palabra clave Overrides

Public Class Animal
   Public Overridable Sub Comer(ByVal a As Alimento)
      Console.WriteLine("Come " & a.ToString)
   End Sub 
   '...
End Class 

Public Class Carnivoro
   Inherits Animal
   Public Overrides Sub Comer(ByVal a As Alimento)
      If Alimento.Type.ToString = "Carne" Then
          MyBase.Comer(a)
          Me.Calorias += a.Peso * 100
      Else
          Me.Regurgitar
      End If
   End Sub 
   '...
End Class 
Public Class Herbivoro
   Inherits Animal
   Public Overrides Sub Comer(ByVal a As Alimento)
      If Alimento.Type.ToString = "Vegetal" Then
          MyBase.Comer(a)
          Me.Calorias += a.Peso * 20
      Else If
          Me.Regurgitar
      End If
   End Sub 
   '...
End Class
'ToDo: Omnívoro 

Si no se utiliza la palabra clave Overrides al intentar remplazar un método, en lugar de "sobre-escribirlo" sólo se está "ensombreciendo" al mismo. Lo cual es la única opción si el método de la clase base no especifica que es remplazable, mas sin embargo debe entonces calificar el metodo "sombra" con la palabra clave Shadows u Overloads, de lo contrario se recibirá una advertencia. Por otro lado Overloads se utiliza cuando se desea cambiar la lista de argumentos del método a "ensombrecer".

Un método reemplazable también puede ser calificado con la palabra clave MustOverride, lo que significa que no proporciona ningún cuerpo de método y que debe ser reemplazado, por ello no puede incluir los modificadores Shared u Overridable. Los métodos MustOverride sólo se permiten en las "clases selladas" las cuales se califican con la palabra clave MustInherit:

En el ejemplo siguiente, la clase Shape define la noción abstracta de un objeto de forma geométrica que puede dibujarse él mismo:

MustInherit Public Class Shape
   Public MustOverride Sub Paint(g As Graphics, r As Rectangle)
End Class 

Public Class Ellipse
   Inherits Shape
   Public Overrides Sub Paint(g As Graphics, r As Rectangle)
      g.drawEllipse(r)
   End Sub 
End Class 

Public Class Box
   Inherits Shape
   Public Overrides Sub Paint(g As Graphics, r As Rectangle)
      g.drawRect(r)
   End Sub 
End Class 

El método Paint es MustOverride porque no existe una implementación predeterminada significativa. Las clases Ellipse y Box son implementaciones Shape concretas. Dado que estas clases no son MustInherit, son necesarias para reemplazar el método Paint y proporcionar una implementación real.

Conclusión

Hasta aquí hemos terminado ésta serie en donde hemos realizado un breve recorrido a los principales conceptos que enmarcan a la Programación Orientada a Objetos así como su aplicación con el lenguaje de programación Visual Basic .NET. Espero que con esto el lector que no conocía a la misma, así como aquel que sólo tenía una idea, hayan resuelto sus dudas y perdido el miedo a este tipo de programación para de ahora en adelante aprovechar los beneficios de la misma con el renovado lenguaje de programación Visual Basic .NET 100% Orientado Objetos.

Si bien existen muchos otros conceptos y técnicas surgidos a partir de la práctica de la POO, los mismos que no fueron parte del objetivo de la serie, pero trataré de abordarlos en siguientes ocasiones. Así que hasta la próxima.

Continuar con POO con Visual Basic .NET Parte 1

posted on Monday, November 14, 2005 9:17 PM by vbpuntonet





Powered by Dot Net Junkies, by Telligent Systems