miércoles, 11 de septiembre de 2013

Usar la herencia para crear clases especializadas

Ajedrez, un programa de ejemplo


Para explicar la herencia, vamos a crear un nuevo programa que juegue al ajedrez, para ello crearemos una clase base llamada CPieza con los atributos comunes a todas las piezas y de ella derivarán las clases hijas CTorre, CCaballo, CAlfil, CDama, CRey y CPeon que incluirán la sobrecarga del método mover() específica de cada tipo de pieza.


Cada pieza incluye los siguientes atributos comunes: Nombre, Color, un atributo booleano que indique si la pieza está en Juego y por último otro atributo que contenga su posición en el tablero.

Usar la herencia para crear clases especializadas
      Private m_nombre as string
      Private m_color as boolean
      Private m_enjuego as boolean
      Private m_posicion as string

Utilizando la herencia, se puede crear una nueva clase de añadiendo o modificando una clase existente. En este documento, vamos a crear una primera clase, CPieza, y a continuación, utilizaremos  la herencia para crear clases especializadas como CTorre, CCaballo, CAlfil etc. La herencia no se limita a las clases que se creen; se puede heredar de muchas de las clases de Microsoft. NET.

El código de cliente creará un array de objetos, con la generación de todas las piezas del tablero, asignando a cada una de ellas sus atributos correspondientes, luego al jugar, se llamará a los diferentes métodos mover, que irán modificando los atributos de cada pieza en función del transcurso de la partida.


Usar la herencia para crear clases especializadas

Esquema teórico


Para evitar errores y escribir programas potentes, se recomienda utilizar la herencia y tener en cuenta las siguientes consideraciones de diseño.


Herencia


La relación tiene-un (clase),  es-un (objeto) es fundamental en el diseño orientado a objetos. Se crean clases que contienen instancias de otras clases. Estos diseños de modelo tienen una relación entre un objeto y sus propiedades (un formulario tiene-un botón)  permiten crear una aplicación mediante la combinación de los objetos ya existentes.

La herencia es el método de programación utilizado para implementar la relación es-un  de  los objetos. Una caja de texto es un control, un coche es un vehículo, un alfil es una pieza de ajedrez. Si ya se ha escrito el código para el modelo propietario de una pieza de ajedrez, CPieza, nos gustaría poder ser capaces de utilizar ese código para todas las piezas del tablero.

La herencia consiste en la creación de nuevas clases derivadas o hijas a partir de clases existentes. A la clase padre también se le puede llamar clase base. También se puede hablar de superclase, clase y subclase, pero la terminología clase base y clase derivada es más adecuada para la programación con Visual Basic.

La relación es-un


Tener en cuenta que la clase derivada que creemos necesite realmente derivarse de la clase base elegida. Es decir que el objeto creado sea realmente un objeto especial derivado del objeto base. Una forma de saberlo es hacerse la pregunta es-un.  ¿Una torre es-una pieza de ajedrez? Si tratamos de eliminar propiedades o métodos de una clase base, debe advertirnos de si realmente el objeto creado debe derivar de la clase base elegida. Por ejemplo si estamos tratando de eliminar el evento mover de la clase pieza para alojar el tablero, es evidente que lo estamos haciendo mal. El tablero NO es-una pieza.

Polimorfismo


Una pieza de ajedrez es un único tipo de pieza de ajedrez CPieza. Pero hay piezas que son peones, torres, alfiles, etc aunque derivan todas de pieza de ajedrez. A esto se llama comportamiento polimórfico y permite a los desarrolladores utilizar una variable Pieza para referirse a cualquiera de las clases derivadas de una pieza de ajedrez. El Polimorfismo describe el comportamiento de las clases que se derivan de una clase base común, También permite que cada clase derivada maneje un método con idéntico nombre pero con un comportamiento diferente. Por ejemplo, el método mover estará presente en cada clase derivada, CPeon, CReina, CCaballo, etc pero será diferente para cada una de ellas.
Aquí nos centraremos en los mecanismos de la herencia. Se pueden desarrollar resultados sofisticados heredando de clases de. NET. Incluso con implementaciones sencillas.

Debemos hacer un estudio de nuestras clases para ver si realmente necesitamos utilizar la herencia. O al contrario, si tenemos muchas clases inconexas debemos preguntarnos si algunas se pueden derivar de otras. También es posible que la clase sólo necesite contener una instancia de la clase en lugar de servir como clase base.

Comprobación de tipos


En general, controlar el  tipo (utilizando el operador type) es un indicio de que se está utilizando la herencia de forma incorrecta. Determinar si se están definiendo correctamente las propiedades y métodos para que la comprobación de tipos no sea necesaria.


Seleccionar o cambiar los estados


Si el código contiene muchos selects o switchs, hay que considerar si el uso de la herencia podría  simplificar el código.

  CPieza: Un ejemplo sencillo


En este ejemplo crearemos una clase base llamada CPieza con los atributos genéricos de una pieza de ajedrez, como su color o su posición, y luego se derivarán varias clases CCaballo, CTorre etc, (Recordar que son derivadas por que un caballo es una pieza de ajedrez, una torre es una pieza de ajedrez, etc.) que además incluirán el comportamiento específico de cada tipo de pieza. En estas clases irá el método Mover() que será específico para cada clase de pieza.

Descripción de los Miembros


programar un juego de ajedrez

 m_nombre as string
Propiedad de sólo lectura que identifica la pieza por su nombre. TD  torre de la dama PTD Peón de torre de la dama, etc.

m_color as boolean
Propiedad de sólo lectura que identifica el color de la pieza  (True = blanca, False = Negra).

Posicion as string
Propiedad que identifica mediante unas coordenadas la posición de cada pieza sobre el tablero.  (Ver esquema de la izquierda)

EnJuego as bolean
Propiedad que identifica si la pieza está en juego (True) o ha sido eliminada (False).


Public Function Mover(Byval Posicion as string) as boolean
Método que será definido en las clases hijas para definir como se mueve cada pieza, pasando como parámetro la casilla de destino este devolverá true si la posición es correcta y false si es prohibida.

Crear la clase base CPieza


Public Class CPieza

    Private m_nombre As String
    Private m_color As Boolean
    Private m_posicion As String
    Private m_enjuego As Boolean

    Public ReadOnly Property Nombre() As String
        Get
            Return m_nombre
        End Get
    End Property

    Public ReadOnly Property Color() As String
        Get
            Return m_color
        End Get
    End Property

    Public Property Posicion() As String
        Get
            Return m_posicion
        End Get
        Set(ByVal value As String)
            m_posicion = value
        End Set
   End Property

    'True si la pieza está en juego, False si la pieza ha sido      capturada
    Public Property EnJuego() As Boolean
        Get
            Return m_enjuego
        End Get
        Set(ByVal value As Boolean)
            m_enjuego = value
        End Set
    End Property

    ‘Constructor
    Public Sub New()
        m_nombre = "TD" 'torre Dama
        m_color = True
        m_posicion = "A1"
        m_enjuego = True
    End Sub
End Class

Creando la clase derivada CTorre


La primera clase derivada se crea será la clase CTorre. En este ejemplo CTorre es idéntica a la clase CPieza, excepto en el método Mover que es específico para la torre.

Public Class CTorre
    Inherits CPieza

End Class

Examinar el entorno de desarrollo


Si pulsamos el botón para ver el diagrama de clases.

Ver el diagrama de clases

Podemos ver un esquema de las clases creadas

diagrama de clases ajedrez

También podemos consultar el visor  de clases

clases del ajedrez

Crear campos de clase usando la palabra clave Protected


Saltar el seguro de protección private.

Para que la clase hija pueda acceder a los campos de la clase padre pero estos sigan siendo privados para el código cliente, se usa la palabra clave protected.

Public Class CPieza
    Protected m_color As Boolean

Ahora en el Class View aparece con una llave. 

clases y propiedades del ajedrez

Crear métodos y propiedades sobrecargados, Overridable


Sobreescritura de miembros, para ello se  hace esto en la clase base.

'Método padre vacio, se definirá en cada clase hija
Public Overridable Function Mover(ByVal NuevaPos As String) As Boolean
        Me.Posicion = NuevaPos
        Return True
End Function
Esta propiedad o método podrá ser sobreescrito en las clases derivadas.

Crear métodos y propiedades sobrecargados Overrides


Para indicarlo en la clase derivada lo marco con la palabra clave Overrides.

'Dada una torre se le indica moverse desde su posición actual a otra posición.
'True si la nueva posisión es correcta, False si es prohibida
Public Overrides Function Mover(ByVal NuevaPos As String) As Boolean

      Dim PosActual As String
      Dim ColActual As String
      Dim FilActual As String
      Dim NuevaCol As String
      Dim NuevaFil As String

        PosActual = Me.Posicion

        ColActual = Mid(PosActual, 1, 1)
        FilActual = Mid(PosActual, 2, 1)

        NuevaCol = Mid(NuevaPos, 1, 1)
        NuevaFil = Mid(NuevaPos, 2, 1)

        If ColActual = NuevaCol Then
            'si se mueve por la misma columna, no importa el valor de la fila, es movimiento correcto
            Me.Posicion = NuevaPos
            Return True
        Else
            If FilActual = NuevaFil Then
                'Si se mueve por la misma fila, no importa el valor de la columna, es movimiento correcto
                Me.Posicion = NuevaPos
                Return True
            Else
                'En cualquier otro caso es movimiento prohibido
                Me.Posicion = PosActual
                Return False
            End If
        End If
       'En cualquier otro caso
        Me.Posicion = PosActual
        Return false
End Function

También se permite el uso de la palabra NotOverridable para marcar explícitamente un miembro como no reemplazable. (Este es el comportamiento predeterminado)

- No podrá cambiar el atributo ReadOnly ni WriteOnly si se quiere sobrescribir una propiedad en una clase derivada.

- No se pueden sobrescribir campos, constantes ni miembros compartidos definidos en la clase base.

- De forma predeterminada los métodos que estén marcados como Overrides en las clases derivadas son reemplazables (Overridable) en las siguientes clases derivadas, por lo que nunca utilizará simultáneamente las palabras Overrides y Overridable.

- Solo se podrá utilizar la palabra NotOverridable en conjunto con la palabra Overrides para declarar un método como No reemplazable.

- No necesitará introducir la palabra Overrides en la clase derivada ni la palabra Overridable en la clase base si está agregando un miembro con el mismo nombre en la clase derivada (Aunque note un mensaje de advertencia).

Además de que no es obligatoria la palabra  Overloads en el miembro de la clase derivada.
A esto se le conoce con el nombre de ‘Sombreado de Miembros’ (Shadows) y podemos indicarle al compilador que interprete estas advertencias como errores o que simplemente las ignore. (Ver propiedades del proyecto).

Usar la palabra clave MyBase


Esta palabra resulta útil cuando desea hacer referencia a un campo, propiedad o método de la
Clase base. Si no ha reemplazado a algún miembro en la clase derivada la expresión Me.miembro y MyBase.miembro harán referencia al mismo miembro y ejecutarán el mismo código, sin embargo cuando en la clase derivada se ha redefinido el Miembro, se tendrá que usar la palabra Mybase si se quiere hacer referencia al miembro de la clase base.

Si en la clase derivada necesito llamar al método sobrecargado de la clase padre utilizo MyBase para evitar sobrecargar la pila.

Public Overrides Property Color() As String

        mybase.Color()
     
End Property

Usar la palabra clave Me


Si es necesario referirse a un propiedad, campo o función de la propia clase o de una clase padre, se puede poner me para referirnos a un objeto de esta clase.

Public Class CPieza

Private m_posicion As String

Public Property Posicion() As String
      Get
            Return m_posicion
      End Get
      Set(ByVal value As String)
            m_posicion = value
      End Set
End Property

Public Function Mover(ByVal NuevaPos As String) As Boolean

        Dim PosActual As String
        PosActual = Me.Posicion
  
End Function

End Class

Añadir el constructor


Los constructores no se heredan, por lo que se debe agregar a la clase derivada. Además, cada vez que se define un constructor hay que incluir una llamada implícita al constructor sin parámetros que pertenece a la clase base.

Public Class CPieza
    Public Sub New()
        Dim posicion As New CTablero
        m_color = True
        posicion.Columnas(1) = 1
        posicion.Filas(1) = 1
        m_posicion = posicion
        m_enjuego = True
    End Sub
End Class

Public Class CTorre
    Inherits CPieza

    Private Sub New()
        MyBase.New()
    End Sub
End Class

Public Class CCaballo
    Inherits CPieza

    Private Sub New()
        MyBase.New()
    End Sub
End Class

Herencia en un control: La Clase CBotonEliptico


Gracias a la herencia, es posible derivar clases de nuestras propias clases pero también de las  clases base suministradas por .NET.  A Continuación crearemos una clase llamada CBotonEliptico que derive de la clase base System.Windows.Forms.Button en este caso sólo será necesario reemplazar el método OnPaint de la clase Button.

Creamos la clase CBotonEliptico, para crear una clase derivada de una clase. NET, se declara la clase e indicamos la clase base.

Añadir la clase  CBotonEliptico


Public Class CBotonEliptico
    Inherits Button
End Class

Sobreescribiendo el Método OnPaint


El método OnPaint se llama cada vez que se dibuja el control en el formulario. La clase base dibuja el rectángulo familiar. Reemplazando el método OnPaint, se puede determinar el aspecto del botón.

Protected Overrides Sub OnPaint(ByVal pevent As System.Windows.Forms.PaintEventArgs)
      Me.Size = New Size(50, 70)
      Dim bEliptico As System.Drawing.Drawing2D.GraphicsPath = New           System.Drawing.Drawing2D.GraphicsPath()
      bEliptico.AddEllipse(New System.Drawing.RectangleF(0, 0, 50,70))
      Me.Region = New Region(bEliptico)
End Sub

Agregar el siguiente código para dibujar el botón elíptico. Además de elíptico, el área clickable del botón también deber ser elíptica.

Para hacer un control que asuma una forma particular, en este caso elíptico, debe
definir su propiedad Región para que se logre esa forma. Se puede crear la forma, utilizando el objeto
GraphicsPath. El objeto GraphicsPath permite crear un dibujo. En este ejemplo, se crea un dibujo mediante la adición de un círculo de GraphicsPath. El tamaño del botón está limitado a 50 por 70 píxeles de modo que se ve una elipse y rellena.

Uso de la Clase


La clase CBotonEliptico se ha definido en el archivo de origen y no aparece en la
caja de herramientas para el arrastre en el formulario. Para agregar una instancia
CBotonEliptico al Form1, se pueden  utilizar los mismos métodos que se utilizaron para crear botones en el anterior documento.

Añadir el Botón Elíptico al formulario


Private Sub BotonEliptico_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
        MessageBox.Show("Hola")
End Sub

En el Form_Load del formulario creamos el objeto

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
      Dim rb As New CBotonEliptico()
      Me.Controls.Add(rb)
      AddHandler (rb.Click), AddressOf BotonEliptico_Click

End Sub

Ejecutando la aplicación tenemos

botón elíptico


Y si pulsamos sobre el área negra aparece.

hola mundo visual basic


viernes, 6 de septiembre de 2013

Crear-modificar un procedimiento almacenado con parámetros de entrada SQL Server

Se explica cómo se crea un procedimiento almacenado (a partir de ahora SP, Stored Procedure) en una Base de Datos de SQL SERVER y como se introducen parámetros de entrada en dicho procedimiento.

Para crear el procedimiento almacenado se pone la palabra clave CREATE, y se ejecuta el siguiente código o similar. Los parámetros de entrada van  después del nombre del SP precedidos de @ y separados por comas excepto el último.

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go


CREATE PROC [PROPIETARIO].[sp_Nombre_Procedimiento] 
@strParametro1      char(14),    
@strParametroN      char(14)
   
AS

Begin transaction
update propietario.tbTabla set strVariable1 = @strParametro1 where strVariableN =  @strParametroN     
Commit transaction

Ejecutamos el código en el analizador de consultas de SQL SERVER, eligiendo la Base de Datos sobre la cual se creará.

Crear modificar un procedimiento almacenado SQL server

Hecho esto, dice que se ha creado correctamente.

Crear modificar un procedimiento almacenado SQL server

Para modificarlo posteriormente se cambia la palabra clave CREATE por ALTER y se pulsa ejecutar de nuevo. Para ver el SP creado o modificado lo buscamos en el explorador de objetos, en programación -> Procedimientos almacenados.

Crear modificar un procedimiento almacenado SQL server

Para ver su código y modificarlo si procede, nos posicionamos sobre el procedimiento almacenado y con el botón derecho del ratón -> modificar

modificar un procedimiento almacenado SQL server


O bien Incluir procedimiento almacenado como

Crear un procedimiento almacenado SQL server


Lo que nos abrirá una ventana con el script para crear, modificar o borrar el SP , también nos permite elegir si deseamos una nueva ventana, un archivo o llevarlo al portapapeles.

viernes, 30 de agosto de 2013

Trabajar con métodos

Este artículo es la continuación de la implementación de un Primer Programa Orientado a Objetos. Aquí veremos cómo crear métodos de la clase, cómo sobrecargarlos y cómo rellenar un ListBox utilizando el objeto ArrayList de .NET. También veremos como agregar un control a un formulario en tiempo de ejecución. Finalmente utilizaremos los métodos para arrastrar y soltar objetos dentro de un formulario.

Consideraciones en el diseño de clases reutilizables


La idea de la POO es hacer que nuestro código pueda ser reutilizable o incluso exportable a otros programas a través del conocido Copiar y Pegar, para hacer esto posible hay que tener en cuenta algunos conceptos importantes:


Abstracción


Cuando se crea una clase, existe la tentación de agregar una gran cantidad de funciones de apoyo, no obstante hay que tener en cuenta que cada método, propiedad o evento que se añada a la clase va a limitar las opciones de reutilización de la clase. También es necesario saber que una clase debe hacer una cosa bien. Si utilizamos una abstracción clara, será más fácil para los desarrolladores, pues sus métodos y propiedades tendrán sentido y su comportamiento será más predecible.


Contención


Una clase es una especie de caja negra donde se almacena un tipo de objeto con datos diversos y los métodos que trabajan con ellos, por ejemplo La clase CHospital puede almacenar Nombres, direcciones, Números de habitación, Historias clínicas o cualquier otra cosa. Por lo tanto, hay que tener cuidado de no hacer ninguna suposición sobre el contexto de la clase. A pesar de que se va a desarrollar una clase en un contexto de una aplicación de Windows, la clase no debe contener ninguna referencia a un formulario.

Es posible que se desee añadir un comportamiento que dependa del código de cliente. Se podría añadir un método que tome un argumento para especificar una forma de tratar la infoirmación. En este caso es mejor agregar un método que cree un objeto específico de .NET
De tal forma que sea utilizable a través de una serie de códigos de cliente más amplia.

Por ejemplo, si se desea agregar código que muestre un dibujo de un hospital para cada hospital agregado. Se puede añadir un método que cree un objeto de .NET Graphics. Esto nos va permitir escribir código para dibujar el hospital en cualquier objeto que contenga un objeto Graphics de .NET.

Código Cliente


Si la clase está bien diseñada, el código de cliente se simplificará mucho, las estructuras de decisión y los bucles estarán contenidos en los métodos de la clase, de este modo no aparecerán en el código de cliente que se limitará a llamadas a los métodos de las clases.


Interfaz


Hay que proporcionar una interfaz completa, pero sin exajerar. Implementar el interfaz lo suficientemente bien como para que un posterior desarrollador  pueda extenderla. Por ejemplo, la clase CHospital tiene un método para dar de alta a un Médico en un hospital y otro para Ubicar un paciente en una sala, pero posteriormente se puede seguir completando, añadiéndo metodos por ejemplo para asignar una especialidad a un médico o un paciente a un médico.


A continuación continuamos añadiendo funcionalidad a la Clase CHospital, en este caso agregaremos un constructor y más métodos.

métodos el la programación orientada a objetos


jueves, 1 de agosto de 2013

Curso básico de análisis orientado a objetos (AOO)

Con la última entrada se completa un curso básico de Análisis Orientado a Objetos.

Análisis orientado a objetos (AOO) V

El modelo Objeto-Comportamiento

Consiste en evaluar el funcionamiento dinámico del sistema obedeciendo a estímulos externos. El modelo se crea siguiendo los siguientes pasos:

-       Evaluación de todos los casos de uso
-       Crear una traza de sucesos para cada caso de uso
-       Identificación de sucesos y comprender como se relacionan con los objetos
-       Construir un diagrama de transición de estados

Evaluación de los casos de uso


Se considera que ocurre un suceso, cada vez que un actor (puede ser humano o no) intercambia información con el sistema. Es importante recordar que un suceso es booleano (o sucede o no sucede) no caben más posibilidades, es decir un suceso no es la información que se intercambia si no solamente la contabilización de dicho suceso.

Por ejemplo una persona se acerca a un cajero automático y realiza las siguientes operaciones:

1-     Introduce la tarjeta en la ranura y teclea su número de 4 cifras. La contraseña se compara con la almacenada en el sistema. Si dicha contraseña es incorrecta un mensaje por pantalla avisará y restaurará el sistema a las condiciones iniciales, si es correcta  muestra un menú y espera la siguiente acción.

2-     El usuario elije sacar dinero y el sistema comprueba si el saldo tecleado es igual a superior al máximo diario  o al saldo disponible en la cuenta. Si es así entrega el dinero y muestra de nuevo el menú, en caso contrario muestra un mensaje indicando la situación entrega la diferencia y muestra el menú con la opción sacar dinero deshabilitada.

3-     El usuario coge el dinero y la tarjeta, si no se detecta la retirada del dinero o de la tarjeta envía un mensaje en pantalla y otro sonoro indicando el olvido. Si la retirada es completa vuelve al estado inicial. Si no persiste la señal unos segundos y vuelve al estado inicial.

La partes subrayadas indican sucesos. Debe buscarse un actor para cada suceso y anotar la información que se intercambia en cada suceso junto con posibles restricciones o condiciones.
Por ejemplo, en el caso en el que el usuario teclea su contraseña de 4 cifras desde el punto de vista del Análisis OO el actor transmite un suceso al teclado, dicho suceso se puede llamar clave_introducida pero la clave concreta en sí, no es una parte esencial del modelo. En este caso, el hecho de introducir la clave no cambia el flujo de control del caso de uso pero la tarea comparar_contraseña si lo cambia pues a partir de aquí el flujo discurrirá por dos caminos diferentes si la contraseña es correcta o incorrecta.
Cuando se han identificado todos los sucesos, se asocian a los objetos que pueden generar sucesos, incluidos los actores

Construcción del diagrama de transición de estados


Para construir este diagrama hay que tener en cuenta dos caracterizaciones diferentes de estados, una que muestra el estado de cada objeto y otra que muestra el estado del sistema en su conjunto.
También hay que distinguir entre características pasivas (estado actual de todos los atributos de un objeto) y características activas que indica el estado actual del objeto en el momento de producirse el cambio de estado.
Un ejemplo de características pasivas de una cuenta corriente en un cajero sería el titular, el Nº de cuenta etc. Las características activas sería el saldo, si la cuenta está anulada o no, etc. Para pasar una transición de estado activo a otro debe ocurrir un suceso (p.ej. sacar dinero y el saldo de la cuenta cambia).  Cada componente de un modelo objeto-comportamiento es una representación de los estados activos de cada objeto y de los sucesos que producen dichos cambios en estos estados activos.
Diagrama de transición de estados
El esquema mostrado arriba se llama de transición de estados, en él cada flecha es una transición de un estado activo de un objeto a otro. Las etiquetas al lado de cada flecha son los sucesos que disparan la transición. Existe el concepto de guarda, que es una condición booleana que posibilita la ocurrencia de una transición.  La guarda de una transición depende de los valores tomados por uno o varios atributos de un objeto. La guarda depende de un estado pasivo del objeto.
Una acción ocurre como consecuencia de una transición, e implica una o más responsabilidades del objeto. Por ejemplo introduce contraseña en el esquema de arriba es una acción.

Hay otro tipo de esquema para representar los estados del sistema, se trata de modelo  de traza de sucesos. En este modelo se indica como un suceso causa una transición del sistema de un estado a otro. Lo sucesos son booleanos. El sistema del cajero automático representado con este tipo de esquema quedaría del siguiente modo:

modelo  de traza de sucesos

En este esquema, el  usuario introduce la contraseña  a través del teclado, el sistema la compara, si es incorrecta avisa de que la contraseña se debe introducir de nuevo, si es correcta muestra el menú de las  operaciones a realizar.