Mostrando entradas con la etiqueta herencia. Mostrar todas las entradas
Mostrando entradas con la etiqueta herencia. Mostrar todas las entradas

sábado, 21 de octubre de 2017

Curso de C#: clases

Clases

Una clase es la plantilla a partir de la cual es posible crear objetos. Todos los objetos de la misma clase comparten la interface (es decir, métodos, campos y propiedades), pero los datos que contiene cada objeto en sus campos y propiedades pueden diferir.
Por su misión específica,  las clases (y las estructuras) se pueden dividir en tres grandes grupos:

Clases que ofrecen un valor

Son aquellas en las que lo principal es el valor que contienen. Por ejemplo, para pagar un artículo de 50 €. Es posible usar un billete de 50 u otro igual, también de 50. O incluso cinco de 10 € Lo importante es pagar los 50 €, pero no los billetes que utilicemos. Los objetos cuyo único interés es su valor son intercambiables, y suelen estar implementados como estructuras (Int32, Int16, Double...).


Curso de  C#: clases

sábado, 10 de mayo de 2014

Visión general de la programación orientada a objetos. (Con Visual Basic .NET)

Pongo a continuación un resumen de los atributos principales del lenguaje Visual Basic .NET así como de  su utilización en programación orientada a Objetos. Este artículo contiene los siguientes puntos:

Definiciones Generales:


Constantes.

Variables static.

Namespaces.

Punto de entrada al programa.

Clases.

Reglas de ámbito de las clases.

Código de clase y código de cliente.

Propiedades de la clase. (Encapsulación).

Propiedades virtuales.

Propiedades de sólo lectura o sólo escritura.

Me y MyClass.

Sobrecarga de Métodos. (Polimorfismo)

Enlaces (Binding) de variables a referencias de objetos.

Herencia.

Reglas de ámbito.

Herencia y sobrecarga de métodos.

MyBase.

Herencia y sobreescritura de métodos.

Herencia y métodos constructores.

Clases selladas no heredables.

Clases abstractas o no instanciables.

Comprobación del tipo de un objeto y Moldeado (Casting).

Miembros compartidos (Shared) de una clase.

Destrucción de Objetos y recolección de basura.

Interfaces.

Estructuras.


Enumeraciones.


Programación orientada a objetos con Visual Basic.NET


miércoles, 18 de septiembre de 2013

Diseñar clases base y clases abstractas

En este artículo, vamos a crear una clase abstracta, una desde la que se debe heredar. En la definición de la clase abstracta, se le determinan los miembros que la clase derivada debe implementar. .NET proporciona varias clases abstractas, diseñadas exclusivamente como clases base para que los desarrolladores las  utilicen para crear nuevas colecciones de clases, también aprenderemos cómo crear miembros de una clase base y de  una clase derivada que tiene el mismo nombre, sin embargo, no se comportan polimórficamente.

Los desarrolladores pueden usar como clases base algunas proporcionadas por el propio entorno .NET diseñadas exclusivamente con este fin para poder crear nuevas clases o colecciones de clases. También es posible que el desarrollador implemente su propia clase base, para ello es necesario determinar los miembros a implementar por las clases derivadas en la clase base.

Clases Abstractas


La abstracción es la característica que nos permite identificar un objeto a través de sus aspectos conceptuales. Las propiedades de los objetos, pueden hacerlos tan distintos que sea difícil reconocer que pertenecen a la misma clase. Por ejemplo dos objetos barco, un crucero y una piragua, su aspecto exterior y tamaño son muy diferentes, sin embargo sabemos que ambos pertenecen a la clase barco.

En el artículo anterior creamos una clase base CPieza y luego derivamos las clases CTorre, CCaballo, CAlfil etc. Como vemos las clases representan el mundo real. Aunque el ajedrez es algo real, es mal ejemplo para explicar las clases abstractas, por que las piezas aunque reales tienen atributos abstractos, así que vamos a pensar  en algo de la vida real.
Por ejemplo una empresa (recordando que las clases deben modelar el mundo real), en dicha empresa hay empleados con diferentes funciones. Por tanto tendremos una clase CEmpleado. Como se ha dicho la empresa tiene distintas funciones para cada empleado, por ejemplo el jefe de fábrica, el jefe de sección, el operario de fresadora, el operario de empaquetadora, etc. La clase CEmpleado deberá definir el comportamiento común de un empleado genérico, a pesar de que nunca existirá un empleado genérico. Utilizaremos la herencia para crear clases derivadas de la clase genérica (abstracta) de empleado.

Otra razón para no crear una clase base, es que se puede crear una instancia y tener la tentación de agregar funcionalidad a la clase base que no es apropiada para derivar clases. Este error es más probable si el diseño se comenzó como una clase normal y corriente CEmpleado y luego derivamos una clase de ella. Supongamos que la empresa comenzó sólo con un tipo de empleado y se creó la clase CEmpleado, cuando la empresa creció, creó  nuevos tipos de empleado y agregó unas clases COperarioM1, COperarioM2 y CJefeSeccion  que se decidió derivar de CEmpleado. Debido a que la nómina de los operarios de máquina iba a tener un incentivo por buen uso de la máquina, al igual que la clase CEmpleado, lo único que se necesitaba era agregar el método Incentivo_Uso a CEmpleado, pero por herencia ahora se debe ofrecer a todos los empleados  ya sean operarios o jefes el incentivo de buen uso de la máquina. La solución a este problema es crear una clase base (abstracta) para COperarioM1, COperarioM2 y CJefeSeccion por ejemplo, CEmpleado_Generico y luego agregar el método Incentivo_Uso1 e IncentivoUso2 respectivamente a las clases COperarioM1 y COperarioM2, de este modo se podrá definir el método para calcular el incentivo, a cada operario en función de su máquina y otros empleados (jefes) no dispondrán de dicho incentivo.

Para evitar la implementación de métodos en las clases base, Visual Basic ofrece la opción de clase base abstracta que permite crear una clase base de la que deriven otras clases pero aunque es posible definir la clase base entera, obliga a implementar los métodos específicos en las clases derivadas. Se pueden declarar referencias a la clase abstracta, pero no se pueden crear instancias de ellas. Como resultado, no se perderá nada del comportamiento polimórfico de las clases derivadas.

Encapsulación


Establece la separación entre el interfaz del objeto y su implementación. Una clase bien encapsulada no debe permitir la modificación directa de  una variable de la clase ni ejecutar métodos que sean internos de la clase.
Un programador podrá utilizar la clase sin necesitar conocer su implementación.

Public.  Será accesible desde todo el código de la clase y de sus clases derivadas, también desde el código de cliente.

Public Function Metodo1

Private. Sólo será accesible desde la propia clase

Private Function Metodo1

Protected. Sólo será accesible desde la propia clase y desde sus clases derivadas

Protected Function Metodo1

Friend.   Será accesible por todo el código de su ensamblado

Friend Function Metodo1

Protected Friend. Será accesible desde el código de su clase y clases derivadas y por todo el código de su ensamblado.

Protected Friend Function Metodo1

Rediseño  de la clase CPieza


La clase CEmpleado_Generico puede ser completamente funcional, y  puede llevar a errores en el programa si alguna vez es  instanciada la clase porque su comportamiento no sería el de una clase COperarioM1 ni una clase CEmpleado. Se tiene que crear la clase CEmpleado_Generico como una clase abstracta.  La clase CEmpleado_Generico tendría una propiedad ID cuyo formato depende del tipo de empleado. Debido a que la propiedad ID depende del tipo de empleado, no hay razón para implementar este método en la clase base y además, no debería implementarse en la clase base. Si se hizo así, la implementación no sería correcta para cualquier tipo de empleado. Usando una propiedad abstracta en la clase base obligamos a implementar este método en las clases derivadas. Volviendo al ejemplo del  ajedrez en este documento, también se agregará el método abstracto Mover  Si este método se implementa en la clase base, no sería válido para ninguna de las clases derivadas.

Se nos puede ocurrir implementar el método
Mover en la  clase base, luego verificamos el tipo de la instancia y posteriormente movemos la pieza dependiendo del tipo que sea. "Esta solución funciona, siempre y cuando sepamos cuales son todas las clases derivadas de la clase base, pero hacer esto limitaría la capacidad de reutilización de la clase base. En general, las clases base no deben contener código que depende de las clases derivadas.

Descripción del diseño usando Lenguaje de Modelado Unificado (UML)


El Lenguaje de Modelado Unificado (UML) es una herramienta gráfica para describir el diseño orientado a objetos. Estas herramientas de desarrollo permiten discutir los diseños con un vocabulario común. También se disminuye la ambigüedad en la especificación. La unidad básica del diagrama de clases es la caja, que representa a la clase:

                                             Lenguaje de Modelado Unificado (UML)



El elemento de clase consta de dos secciones a continuación del nombre, uno para especificar las propiedades y otro para especificar los métodos:

                                     Lenguaje de Modelado Unificado (UML)

El diagrama muestra la clase base abstracta CPieza. El título en cursiva indica que CPieza es una clase abstracta. En UML  se indican los valores por defecto de las listas de propiedades, y especifica las propiedades públicas colocando un signo más delante de ellas.

A continuación, en la parte inferior del cuadro se enumeran los métodos públicos definidos en la clase. UML también indica los parámetros de los métodos y sus valores de retorno. La  palabra “in” indica que el parámetro se pasa por valor. Aquí se muestra el diagrama completo de clases UML.

                             Lenguaje de Modelado Unificado (UML)


UML también muestra las clases derivadas de la relación de herencia mediante una flecha que apunta hacia la clase base. Las clases derivadas heredarán todo de la clase base, por lo que no se muestran los métodos, sólo se muestran si hay  adiciones en las clases derivadas.

El diagrama de clases UML no especifica el comportamiento de la interfaz. Por ejemplo, No se explica cómo deben implementarse las propiedades ni los métodos.


Creando la Clase abstracta


La primera clase que creamos era CPieza, vamos a declararla de nuevo como clase abstracta, para ello basta con hacer.

Public MustInherit Class CPieza

La declaración de las variables y métodos no abstractos, se queda como estaban en el anterior documento, pero las funciones abstractas ya no pueden llevar implementación por lo que quedan del siguiente modo.


Añadir miembros abstractos


'Método padre vacio, se definirá en cada clase hija
Public MustOverride Function Mover(ByVal NuevaPos As String) As Boolean

La declaración en la clase base no se puede implementar porque se debe hacer en   la clase derivada. Al añadir la palabra clave MustOverride, se obliga a que la propiedad o método se definan en cada clase derivada.
Si se declara uno de los miembros de una clase utilizando esta palabra clave, También se debe declarar la clase como abstracta. Los elementos declarados permanecen como lista de tareas hasta  que se implemente. Sin embargo, si se declara una clase como abstractano obliga a dejar vacías las declaraciones de cualquiera de los miembros de la clase abstracta.

Si hay múltiples niveles de herencia hay que aplicar algunas normas:
Supongamos por ejemplo, que se utilice CPieza como una clase base para las clases CTorre y CCaballo. Si se implementa Mover en CPieza, no se está obligado a implementarlo en  CTorre y CCaballo. CTorre y CCaballo pueden heredar la implementación que haya en CPieza.

Si el método en la clase padre se declara MustOverride, se obligará a declararlo en las clases hijas.  En este caso la declaración del método no se pone.

Una Clase Colección


Existe en la biblioteca de clases de  .NET una clase ya creada llamada ArrayList es muy flexible porque se puede añadir cualquier tipo de objeto a la misma. La desventaja de usar la clase ArrayList es que se puede agregar accidentalmente un objeto que no sea del tipo de la clase, es posible que se produzca un error cuando se recupere el objeto de la clase ArrayList.

Una manera razonable de evitar errores en la conversión de tipos es crear una clase que acepte un único tipo de instancia de tipo CPieza y devuelva sólo los casos de instancias de CPieza.
.NET proporciona la clase abstracta collection que se puede utilizar como clase base para las clases colección escritas. La clase  collection sólo permite agregar o quitar un tipo de objeto. Esto significa los errores aparecerán en tiempo de compilación en lugar de en tiempo de ejecución.


Derivar de una clase abstracta de .NET para crear una clase Colección


En la documentación de las clases System.Collections.DictionaryBase dice: "Proporciona la clase base abstracta (MustInherit) de la clase base para una colección con establecimiento inflexible de las claves y valores asociados”.

Añadir el método Añadir


Vamos a crear un array de piezas en la clase CPieza, para ello utilizaremos la clase base predefinida para las colecciones. En la declaración de la clase ponemos:

Public Class CPieza

    Inherits System.Collections.DictionaryBase  'Se usará para crear         un array de piezas.

Después añadimos el procedimiento Añadir que añade una instancia de CPieza a la colección.

Public Sub Añadir(ByVal unaPieza As CPieza)
      Me.Dictionary.Add(unaPieza.Nombre, unaPieza)
End Sub

Ahora nadie va a ser capaz de añadir nada a la colección que no sea una instancia de CPieza Además, la pieza siempre será mostrada con su nombre.

Añadir el método Eliminar


Public Sub Eliminar(ByVal title As CPieza)
        Me.Dictionary.Remove(title)
End Sub

Añadir la propiedad  ExistePieza


Esta propiedad lleva delante la palabra clave Default que significa que cuando llamamos al entrar en la clase CPieza lo primero que se ejecuta es esta propiedad que verifica si la pieza a meter ya existe en la colección.

Default Public ReadOnly Property ExistePieza (ByVal title As String) As CPieza
        Get
            If Me.Dictionary.Contains(title) Then
                Return CType(Me.Dictionary(title), CPieza)
            Else
                Return Nothing
            End If
        End Get
End Property

Si queremos crear un par de funciones en el código cliente para añadir y eliminar objetos de la colección, en el código del Formulario podemos hacer

Private m_Piezas As New CPieza

Public Sub MeterPieza(ByVal nuevaPieza As CPieza)
      m_Piezas.Añadir(nuevaPieza)
End Sub

Public Function SacarPieza(ByVal title As CPieza) As CPieza
      Dim Pieza As CPieza = m_Piezas
      m_Piezas.Eliminar(title)
      Return (Pieza)
End Function
                                      
Y entonces en el Form_load podemos hacer lo siguiente

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

  Dim T As New CTorre
  Dim EnColeccion As CPieza

  T.Nombre = "TD"
  T.Añadir(T)  'añadir una torre directamente a la colección
  MeterPieza(T) 'añadir una torre a través de las funciones cliente

  EnColeccion = T.ExistePieza("TD") 'recupera la torre de la colección

  T.Eliminar(T)  'Elimina la torre directamente de la colección
  SacarPieza(T)  'Elimina la torre a través de las funciones cliente

End Sub

Variaciones en la herencia


Hay otras dos variaciones de la herencia que merecen una mención. Las clases selladas
que permiten impedir la herencia. También pueden impedir que los miembros de la base se comporten polimórficamente.

Clases Selladas


Algunas veces no se debe permitir a los programadores usar una clase como clase base, se puede prevenir esto usando la palabra clave  NotInheritable:

NotInheritable Class NotABaseClass
End Class


Ocultar miembros de clase base


La palabra clave Shadows  indica que aunque un método en la clase derivada tenga el mismo nombre que un método virtual en la clase base, el método de la clase derivada no está destinado a ser el reemplazo del de la clase base del método virtual de la clase. El efecto es que una referencia a la clase  base llama al método base y una referencia a la clase derivada llama al método derivado. La palabra clave Shadows se aplica a todos los métodos del mismo nombre en la clase base.

Class ClaseBase
      Public Sub MetodoBase()
            Console.WriteLine("MetodoBase en Clase base.")
      End Sub
End Class

Class ClaseDerivada
      Inherits ClaseBase

      Public Shadows Sub MetodoBase()
            Console.WriteLine("MetodoBase in clase derivada.")
      End Sub

      Public Shared Sub Main()
            Dim derivado As New ClaseDerivada()
            derivado.MetodoBase()

            Dim base As ClaseBase = derivado
            base.MetodoBase()
      End Sub
End Class

La salida de Main es
MetodoBase en la clase derivada.
MetodoBase en la clase base.

Se debe usar Shadows con precaución, pues los programadores esperan derivar clases preferentemente para actuar polimórficamente.


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