{ WillyXoft .NET }

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

<July 2008>
SuMoTuWeThFrSa
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789


Navigation

e-Grupos / Foros

Web/Blog Amigos

INETA & MUGs

Subscriptions

News

Post Categories

Article Categories



POO con VB.NET

Serie de Programación Orientada a Objetos con Visual Basic .NET

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 Monday, November 14, 2005 9:17 PM by vbpuntonet with 1 Comments

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

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

Por Willy Mejía [WillyXoft]

POO con VB.NET

En primer lugar debemos tener en cuenta que todo en el .NET Framework, y por ende en Visual Basic .NET, puede ser tratado como un objeto. Por ejemplo el tipo Integer ahora posee propiedaes y métodos, tales como MaxValue que regresa el valor máximo que puede contener:

Dim i as Integer
MsgBox(i.MaxValue)

Con VB.NET observamos que tipos "básicos" como Integer se tratan de objetos. Del mismo modo, entidades tales como los formularios y controles son todos instancias de alguna clase, es decir: objetos. Por ende una de las primeras cosas que debemos tomar en cuenta es que el modo de tratar a éstos tipos a cambiado con respecto a VB6 y versiones anteriores.

No obstante que todo puede ser tratado como un objeto, existen tipos por valor y por referencia. Los tipos por valor como Integer no devuelven una referencia sino sólo el valor que contiene, y sus método en lugar de modificar su estado o el valor contenido, sólo devuelven el valor modificado.

Definiendo Clases

Dado que los objetos se crean a partir de clases, son las clases las que tenemos que diseñar y construir. Para ellos debemos recordar que las clases se componen de los siguientes elementos o miembros:

  • Atributos: Representan la información que contiene un objeto (estado).
  • Métodos: Representan acciones que un objeto puede realizar.

Adicionalemente las clases puede definir Eventos, que son notificaciones que un objeto recibe de, o transmite a, otros objetos, cuando se produce un acontecimiento específico.

También existen los miembros compartidos de clase, que pueden utilizarse en instancias de una clase y en variables de objeto declaradas como tipo de la clase. En otras palabras, no requieren una instancia de clase en específico para realizar su cometido.

VB5 introdujo el concepto de módulo de clase en el cual podían definirse clases simples, una por cada múdulo. Con VB.NET se pueden crear cualquier número de clases en un mismo archivo, no obstante es una buena práctica el definir clases en archivos separados. Para definir una clase se emplea, como entonces, la palabra clave Class:

Class CCliente
    'TODO: Miembros de clase
End Class
Si se requiere, también se pueden crear clases anidadas, es decir, clases dentro de otras clases. Que resulta útil cuando cierto objeto va a ser utilizado al interior de otro y nunca fuera del mismo.

Ahora como experimento abra el entorno de Visual Studio (o bien su Visual Basic .NET Standard ó VB2005 Express) y genere una nueva Aplicación Windows. Despues abra el archivo de código fuente del formulario y observe que inicia con algo como:

Public Class Form1

Lo cual implica que el formulario se construye a partir de una Clase.

Incluso ahora los Modulos de código son clases, la única diferencia es que se trata de Clases estáticas con mienbros compartidos.

Ahora pasemos a definir los miembros de la clase: los atributos y métodos

Atributos

Los atributos de clase se representan mediante Campos o Propiedades. Los Campos se implementan mediante variables públicas que se pueden leer y establecer directamente desde el exterior de la clase.

Public Nombre As String

Mientras que las Propiedades se recuperan y establecen como los Campos, pero se implementan mediante procedimientos Property Get y Property Set. El acceso a los atributos mediante procedimientos proporciona un mayor control sobre la forma en que se establecen o se devuelven los valores de los atributos; esto ayuda a aislar los datos y permite validar valores antes de ser asignados o recuperados.

Por ello también podriamos ver a las Propiedades como métodos de clase ya que encajan en la definición y propósito de los mismos. De hecho en lenguajes como Java no existen las propiedades y las operaciones de asignación (Set) y obtención (Get) del valor de los atributos se realizan mediante métodos.

Se puede definir una propiedad de la siguiente manera:

' Ahora el atributo es Privado
Private strNombre As String
' Para ser accesible mediante la Propiedad
Property Nombre() As String
    Get
        Return strNombre
    End Get
    Set(ByVal Value As String)
        strName = Value
    End Set
End Property

El procedimiento Get devuelve el valor de la propiedad, mientras que el procedimiento Set le asigna el valor a la propiedad. Observe que dado que todo en .NET es un objeto ya no es necesario la sentencia Let, así como que ambos procedimientos están contenidos dentro una sola sentencia Property, lo cual hace mas fácil de manipular y mantener el código de la Propiedad.

En aplicaciones de N-capas las clases generalmente se diseñan sin estado, es decir sin propiedades.

Métodos

Los métodos de una clase en VB.NET se implementan mediante procedimientos o subrutinas (Sub) y funciones (Function) declarados dentro de una clase, de la misma manera como se realizaba anteriormente. No obstante ahora para devolver el valor desde una función se utiliza la palabra clave Return en lugar del nombre de la misma, el cual además se puede utilizar en los diferentes puntos de salida de la función:

Function Hola() As String
    If Nombre <> "" Then
        Return "Hola " & Nombre
    Else
        Return "Hola Mundo"
    End If
End Function
Aún se puede seguir utilizando, por compatibilidad hacia atrás, el nombre de la función para devolver el valor. Mas es recomendable utilizar Return dado que tiene un comportamiento más estructurado.

Constructores y Destructores

Los constructores y destructores son métodos especiales que como su nombre indica, se emplean para la inicialización del objeto durante su construcción, y la limpieza del mismo durante su destrucción.

En VB5 y VB6 las tareas de inicialización se implementan en el procedimiento Initialize. Este procedimiento no permite el paso de parámetro alguno, lo cual dificulta establecer el estado inicial del objeto durante su creación. Visual Basic .NET sin embargo introduce verdaderos constructores que se defininen con el procedimiento New:

Sub New()
    'Código de Inicializacion
End Sub
Esta es la definición del constructor por omisión, la cual será agregada por VB si no se define de manera explícita constructor alguno en una clase.

Dicho procedimiento permite la definicón de parámetros, lo que significa que pueden crearse constructores parametrizados.

Sub New(Nombre String)
    strNombre = Nombre
End Sub
Con VB6 y anteriores los parámetros por omisión eran de paso por referencia, con VB.NET ahora son por valor.

Y aun hay más, una clase puede tener cualquier cantidad de constructores, siempre y cuando tengan diferente tipo y/o número de parámetros.

Sub New()
...
Sub New(Nombre As String)
...
Sub New(Nombre As String, Edad As Integer)
A ésta característica se le conoce como sobrecarga de métodos de clase, por lo que se dice del método que emplea la misma que es un método sobrecargado, y en el caso de una clase con más de un constructor se dice que tiene un constructor sobrecargado.

En cuanto al destructor, Visual Basic .NET lo provee mediante el procedimiento Finalize que no puede ser sobrecargado, es decir, que únicamente puede existir un sólo destructor Finalize en cada clase.

Overrides Protected Sub Finalize()

Finalize está protegido (detalles sobre ésto mas adelante en Encapsulación) lo que implica que no puede invocarse de manera directa por el consumidor de la clase. La ejecución del código del destructor corre a cargo del Colector de Basura del .NET Framework (GC: Garbage Collector) una vez que el objeto pase a ser inaccesible. La excepción a la regla obedece al hecho que todas las implementaciones de Finalize en una clase derivada deben llamar a la correspondiente implementación de Finalize de la clase base (eso implica Overrides que veremos más adelante en Herencia). Este es el único caso en el que se permite al código de la aplicación llamar a Finalize.

Hay que tener mucho cuidado con las operaciones de Finalize, dado que su ejecución corre a cargo del GC tienen las siguientes limitaciones:

  • No se garantiza la liberación de recursos en un momento concreto; y
  • No se garantiza que los finalizadores de dos objetos se ejecuten en un orden determinado, aunque un objeto haga referencia al otro.
Por ello aquellas clases que requieran la liberación controlada de recursos deben implementar la interface IDisposable e implementar el método Dispose() con el código necesario para la liberación de los recursos. A diferencia de Finalize, Dispose si puede invocarse de manera manual. Se abordará el tema de Dispose mas adelante.

Creando y Destruyendo Objetos

Para crear un objeto, seguimos utilizando la cláusula New:

Private mCliente As CCliente
mCliente = New CCliente()
Observe que ya no se utiliza más la palabra Set al asignar la variable al objeto, dado que ahora todo es un objeto ya no es necesaria la diferenciación y se excluido del lenguaje.

También, como antes, se pueden realizar ambas operaciones en la misma línea:

Private mCliente As CCliente = New CCliente()

O incluso de la manera abreviada:

Private mCliente As New CCliente()
Aquí existe otra diferencia, con VB6 y anteriores este tipo de asignación inicializaban el objeto en Nothing y creaba el objeto sólo hasta que era utilizado, con VB.NET el objeto es creado desde el primer momento, cuando se utiliza la cláusula New. Por ello se recomienda dejar de lado ésta práctica y crear el objeto cuando se vaya a utilizar.

Si el constructor admite parámetros se colocan entre los paréntesis:

mCliente = New CCliente("Luz", 18)

Como hemos visto la destrucción del objeto corre a cargo del Recolector de Basura (GC) por lo que no podemos destruir un objeto manualmente. Pero lo que sí podemos hacer una vez utilizado el objeto, es invocar el método Dispose, si está disponible en el objeto.

mCliente.Dispose()
No se confunda, al momento de invocar el método Dispose sólo se liberan los recursos utilizados por el objeto, mas el objeto no es destruido.

Eventos

Se pueden utilizar los eventos para notificar a los objetos sobro la ocurrencia de alguna situación especial. Los eventos se agregan a una clase con la instrucción Events. La declaración incluye el nombre del evento y los argumentos que utiliza.

Event MiEvento(ByVal sender As System.Object, _ 
   ByVal NumEvento As Integer)

Y al igual que antes, para conseguir que se produzca el evento, se debe utilizar la instrucción RaiseEvent.

RaiseEvent MiEvento(Me, NumEvento)
Los eventos deben producirse dentro del ámbito en el que se han declarado. Por ejemplo, una clase derivada no puede producir eventos heredados de una clase base.

A diferencia de VB6 y anteriores, para consumir un evento se necesita asociar de manera explícita el evento a un método (procedimiento) controlador de evento (event handler) para lo cual se utiliza la cláusula Handles en combinación con WithEvents.

Friend WithEvents Button1 As System.Windows.Forms.Button
Protected Sub Button1_Click(ByVal sender As System.Object, _ 
   ByVal e As System.EventArgs) Handles Button1.Click
End Sub

También se puede asociar un evento a un método controlador de evento con la instrucción AddHandler que permite que un evento pueda asignarse a cualquier número de controladores de eventos.

AddHandler MyObject.Event1, AddressOf Me.MyEventHandler

Además, los métodos que controlan determinados eventos pueden modificarse de manera dinámica, si se utiliza en conjunto con la instrucción RemoveHandler, que remueve la asociación entre un evento y su controlador.

RemoveHandler MyObject.Event1, AddressOf Me.MyEventHandler

Tanto AddHandler y RemoveHandler toman dos argumentos: el nombre del evento, y una expresión que evalúa a un Delegado con la instrucción AddressOf, la cual devuelve una referencia (apuntador) de un Delegado. Pero eso se verá con detalle más adelante, por el momento sólo pruebe el siguiente ejemplo:

Public Class ClasePublicadora
   Public Event ElEvento()
   Sub ProduceEvento()
      RaiseEvent ElEvento()
   End Sub
End Class
Public Class ClaseConsumidora
   Sub TestEvento()
      Dim Obj As New ClasePublicadora()
      ' Asociamos el evento con un controlador.
      AddHandler Obj.ElEvento, AddressOf ControladorEvento
      ' Provocamos que se produzca el evento...
      Obj.ProduceEvento()
      ' Removemos el controlador.
      RemoveHandler Obj.ElEvento, AddressOf ControladorEvento
      ' Ya no pasa nada...
      Obj.ProduceEvento()
   End Sub
   Sub ControladorEvento()
      System.Windows.Forms.MessageBox.Write("Evento controlado.")
   End Sub
End Class

Para mayor información al respecto léa:  Los delegados y el operador AddressOf.

Continuar con POO con Visual Basic .NET Parte 3

posted Monday, November 14, 2005 9:14 PM by vbpuntonet with 1 Comments

POO con Visual Basic .NET Parte 1 Rated Average [3 out of 5].

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

Por Willy Mejía [WillyXoft]

Introducción a la POO

La Programación Orientada a Objetos (POO) es la aproximación de desarrollo de software en el cual la estructura de el software se basa en la observación de que, en el mundo real, los objetos se contruyen a partir de otros objetos y que éstos a su vez interactúan para cumplir una tarea. Por esta razón utiliza mecanismos y características para la creación y utilización de objetos. Un mecanismo importante es la Clase y de la cual el Encapsulamiento y la Herencia son dos características o propiedades importantes.

Ventajas de la POO

Anterior a la POO existían otros modelos de programación --entre ellos la programación estructurada-- los cuales presentaban ciertos problemas, táles como:

  • Programas monolitcos dificiles de mantener.
  • Dificultad de modificación de una parte sin afectar al sistema entero.
  • No aprovechamiento de código existente, siendo cada programa construido desde cero.
  • Dificultad en la separación de tareas y responsabilidades, todo programador tenía que conocer cada parte del sistema.
  • Dificultad para transmitir lo modelos de negocios en los modelos de programación.
  • Dificultad en la integracion de sistemas.
El hecho de utilizar un lenguaje POO no implica que ya no tendremos los problemas citados, para ello debemos de realmente programar orientados a objetos y olvidar antiguas prácticas de la programación. De nada sirve tener una sola clase llamada Program con un sólo método llamado Main.

Las metodologias Orientados a Objetos resuelven en cierta medida los problemas anteriormente listados y proporcionan los siguientes beneficios:

  • Transición intuitiva de los modelos de análisis de negocios a los modelos de implementación de software.
  • Mantenimiento e implementación de cambios más eficiente y rápida
  • Permite separar partes del sistema para trabajar en ellos sin afectar al resto del mismo.
  • Permite la reutilización de código de componentes en otros sistemas e incorporar componentes de terceros.
  • Permite una mejor integracion de sistemas distribuidos con un bajo acoplamiento.
  • Mejores interfaces graficas y componentes al aprovechar frameworks preconstruidos y probados.
Del misma modo, para obtener éstas ventajas debemos de aplicar a nuestro software los principios y metodologias de la POO.

Conceptos de la POO

Los conceptos de la POO comenzaron a circular a mediados de la década de 1960s con el lenguaje Simula que posteriormente evolucionaron una década despues con Smalltalk, pero su adopción era mas bien académica. En los años 80s resurgió el interés en las metodologías orientadas a objetos, cuando lenguajes como C++ y Eifle (que permiten la construcción y manipulacion de objetos) se volvieron populares, haciendo que la POO pasara al mundo productivo. Desde entonces la POO a ganado cada vez mayor popularidad y generando nuevos lenguajes, primero fue Java a finales del siglo 20, y actualmente los lenguajes .NET, C# y el renovado Visual Basic: VB.NET.

La POO utiliza objetos para modelar el dominio del problema de un sistema y para ello se basa en cuatro principios básicos perseguidos por el modelado de software: Modularidad, Abstracción, Encapsulación y Jerarquía; que sólo la orientación a objetos cumple en mayor medida que otros estilos de modelado.

  • Modularidad: Es la descomposición lógica de un sistema en entidades más pequeñas. En POO permiten descomponer el problema en unidades discretas más simples. De esta manera se logra reducir la complejidad de la construcción de un sistema al dividirlo en unidades mas pequeñas y manejables, a la vez que permite el intercambio de las mismas. Dichas unidades o módulos tienen entre sí un grado de cohesión y de acoplamiento.
    • Cohesion: Es el grado con el cual las responsabilidades de un módulo forman una unidad significativa por lo que un alto grado de cohesion es mejor.
    • Acoplamiento: Es el grado de mutua interdependencia entre módulos, por lo que un bajo grado de acoplamiento es mejor.

    Es decir que lo ideal es que las unidades en las que se descompone un sistema: los módulos, deben ser altamente cohesivos pero con un bajo acoplamiento, permitiendo que los módulos trabajen entre sí como una sola unidad (el sistema) y que la actualización de un módulo no afecte al resto del sistema.

  • Abstracción: Es la acción de separar por medio de una operación intelectual las cualidades de un objeto de un todo para considerarlas aisladamente y de esa manera conceptualizar al objeto en su mas pura esencia o noción. En POO expresa la acción de conceptualizar a los elementos de un sistema (los módulos) excluyendo aquellos elementos que no son relevantes para la solución del problema, es decir, excluyendo aquellos aspectos (atributos y comportamientos) que no son importantes según el dominio del problema, haciendo mayor énfasis en el "qué hace" el objeto sobre el "cómo lo hace".

Por ejemplo: La representación abstracta de Empleado tiene como atributos: Nombre, Salario e Identificador. Pero no su Estatura o Edad, a menos que sean relevantes para el dominio del problema.

Por otra parte, en términos de la POO, una representación abstracta no es otra cosa que el mecanismo utilizado por ésta para construir objetos, al cual se le conoce como Clase.

Clase: Es el orden en el que, con arreglo a determinadas condiciones o calidades, se consideran comprendidas diferentes cosas. En POO es una representación abstracta de un conjunto de elementos del sistema que tienen las mismas características y comportamientos, y a partir de la cual se pueden crear ejemplares u objetos utilizables.

Es decir que una clase equivale a la generalización de un tipo específico de objetos. Mientras que un objeto es una representación concreta y específica de una clase, por lo que se dice también que es una instancia de clase.

  • Encapsulación: Es la acción de colocar algo dentro de un contenedor protector. En POO es la capacidad de una representacion abstracta (clase) de ocultar la implementación de sus atributos y comportamientos, restringiendo el acceso externo a los datos guardados por una instancia, denominado estado. Dicho estado es manipulado de manera controlada mendiante una serie de métodos, denominada interfaz, definidos para la interactuación con otras instancias a través de mensajes (invocación de métodos).

Por ejemplo: La Cerradura tiene una interfaz de "giro a la derecha" que abre y "giro a la izquierda" que cierra, pero el modo en que internamente lo realiza permanece oculto.

Con ésto se logra que los datos de los sistemas sean más seguros y confiables, al controlar el modo en que éstos son modificados. Por otro lado facilita la separación de tareas ya que otro objeto sólo necesita conocer su interfaz para poder enviarle mensajes y colaborar con él, sin necesidad de conocer su implementación y viceversa.

  • Jerarquía: Clasificación u ordenación segun un grado de valor o dependencia. En POO se refiere a la organización entre las diferentes representaciones abstractas que comprenden el sistema