Mostrando entradas con la etiqueta programacion orientada a objetos. Mostrar todas las entradas
Mostrando entradas con la etiqueta programacion orientada a objetos. Mostrar todas las entradas

sábado, 9 de julio de 2022

Curso avanzado de C#. Creación e implementación de jerarquías de clases

Heredar de una clase base La sección "Creación de tipos de referencia", explica cómo crear clases. El siguiente código muestra la definición de una clase Persona simple y debe ser familiar para  nosotros

Public Class Persona

{

       Public String Nombre { Get; Set; }

       Public String Apellido { Get; Set; }

       Public Persona(String nombre, String apellido)

       {

             // Valida el nombre y el apellido

             If (( nombre == null) || (nombre .Length < 1))

                    Throw New ArgumentOutOfRangeException(

                    "Nombre", nombre,

                    "El nombre no puede ser nulo o quedar en blanco.");

             If ((apellido == null) || (apellido .Length < 1))

                    Throw New ArgumentOutOfRangeException(

                    "Apellido", apellido,

                    "El  apellido no puede ser nulo o quedar en blanco.");

                    // Guarda el nombre y el apellido.

                    Nombre = nombre;

                    Apellido = apellido;

       }

}

La clase Persona contiene dos propiedades de cadena implementadas automáticamente: Nombre y Apellido. (Una clase utilizada por una aplicación real probablemente tendría muchas más propiedades para contener información como como la dirección postal, números de teléfono y direcciones de correo electrónico). Nuestro constructor toma los nombres y apellidos como parámetros, realiza alguna validación y guarda los valores en las propiedades Nombre y Apellido.

Curso avanzado de C#. Creación e implementación de jerarquías de clases
Fotos similares a esta aquí


Ahora supongamos que queremos  crear una clase de Empleado que tenga las propiedades Nombre, Apellido y NombreDepartamento. Podemos construir esta clase desde cero, pero necesitaremos las mismas propiedades que las de la clase Persona y necesitaremos las mismas validaciones, por lo que crearlo desde cero requeriría duplicar  todo ese código. Una mejor solución es derivar la clase Empleado de la clase Persona para que herede de la clase padre los campos, propiedades, métodos y eventos. Un empleado es una especie de persona, por lo que tiene sentido que la clase Empleado derive desde la clase Persona. No hay ninguna razón por la que el mismo código dentro de la clase Persona no funcionara también para los objetos  de la clase Empleado. 

Terminología de clases

Hay mucha terminología en torno a las jerarquías de clases. Cuando derivamos una clase de otra, la nueva clase hereda todo el código incluido en la clase original. En este caso, la clase original se llama padre clase, clase base o superclase. La nueva clase se llama clase derivada, hija, secundaria, o subclase. Derivar una clase de otra se llama subclasificación. 

_________________________________________________


Para derivar una clase de otra, simplemente hay que poner el nombre de la clase con dos puntos y luego el nombre de la clase principal. El siguiente código muestra una clase  empleado que se deriva de la clase persona. 

Public Class Empleado :  Persona

{

    Public String NombreDepartamento { Get; Set; }

}

En este ejemplo, la clase Empleado hereda los campos, propiedades, métodos y eventos definidos por la clase Persona. También agrega una nueva propiedad, Nombre Departamento. Aunque una clase secundaria hereda la mayoría del código en su clase padre, no hereda el constructor de la clase. En este punto, un programa podría utilizar el siguiente código para crear un objeto Empleado sin inicializar sus propiedades Nombre y Apellido:

Empleado empleado = new Empleado();

Dado que este código no inicializa las propiedades Nombre y Apellido del empleado, estas tienen los valores nulos, lo que anula el propósito del constructor de la clase Persona. La solución es hacer que los constructores de la clase secundaria llamen a los constructores de la clase principal. 

Llamar a constructores de clases principales 

Para asegurarse de que se llama al constructor de la clase Persona para validar el Nombre y Apellido del empleado. Debemos darle un constructor a la clase Empleado, con  una lista de argumentos del constructor seguida por dos puntos, la clase base y cualquier parámetro que deseemos pasar al constructor de la clase base.

En este ejemplo, el constructor Empleado debe pasar el nombre y apellido que recibe al Constructor de la clase de persona. El código resaltado muestra dónde el constructor llama al constructor de la clase base : 

Public Class Empleado :  Persona

{

      Public String NombreDepartamento { Get; Set; }

      Public Empleado(String Nombre, string Apellido,

      string nombredepartamento)

            :base(Nombre, Apellido)

      {

            // Valida NombreDepartamento.

            If ((nombredepartamento == null) || (nombredepartamento.Length < 1))

            Throw New ArgumentOutOfRangeException(

            "nombredepartmento", nombredepartmento,

            "NombreDepartamento no debe ser nulo o estar en vacío.");

            // Graba el Nombre del Departamento.

            NombreDepartmento = nombreDepartmento;

      }

}

Si la clase base tiene varios constructores, la clase secundaria puede usar la palabra clave base para invocar cualquiera de ellos. El programa usa los argumentos que siguen a la palabra clave base para averiguar qué constructor utilizar. 

Nota: Cuando un constructor utiliza la palabra clave base para invocar un constructor de la clase base, El constructor de la clase base se ejecuta antes que el cuerpo del hijo. 

Si tanto la clase principal como la secundaria tienen constructores, el constructor de la clase secundaria debe invocar uno de los constructores de la clase padre. Esto significa que la llamada al constructor en la clase base que hemos resaltado arriba, requiere un fragmento de código. Si eliminamos ese código, Visual Studio muestra el mensaje de error "JerarquiaPersona no contiene un constructor que tome 0 argumentos". (Aquí, JerarquiaPersona es el espacio de nombres que contiene la clase Persona.) El constructor de la clase Empleado está tratando implícitamente de acceder a un constructor de Persona que no toma parámetros y no puede encontrar uno. Una rareza de este sistema es que podemos crear una clase Empleado sin constructores aunque  permite al programa crear una instancia de la clase Empleado sin invocar un constructor de la clase Persona. Eso significa que la siguiente definición para la clase Empleado es legal: 

Public Class Empleado :  Persona

{

      Public String NombreDepartamento { Get; Set; }

}

Si deseamos evitar que el programa eluda los constructores de la clase principal, debemos dotar la clase secundaria de al menos un constructor.

Llamar a constructores de la misma clase 

A menudo, es conveniente dar a una clase varios constructores para realizar diferentes tipos de inicialización. Dependiendo de qué parámetros se pasen al constructor. En ese caso, varios constructores puede que necesiten realizar las mismas tareas. Por ejemplo, supongamos que la clase Persona tiene las propiedades Nombre y Apellido y queremos permitir que el programa cree un objeto Persona especificando solo el nombre o nombre y apellido. 

Class Persona

{

     Public String Nombre { Get; Set; }

     Public String Apellido { Get; Set; }

     // Constructor con nombre.

     Public Persona(String nombre)

     {

          Nombre = nombre;

     }

     // Constructor con Nombre y Apellido.

     Public Persona(String nombre, String apellido)

     {

          Nombre =  nombre;

          Apellido = apellido;

     }

}

El primer constructor toma un nombre como parámetro y lo almacena en la propiedad Nombre. El segundo constructor toma el nombre y el apellido como parámetros y guarda sus valores en las Propiedades Nombre y Apellido. En este código, el segundo constructor comienza realizando el mismo trabajo que el primer constructor hace cuando guarda el nombre. En un escenario mas complicado en el que los constructores realizan tareas más difíciles, esta repetición de código sería un problema. Significaría varias copias del mismo código para implementar, depurar y mantener. Una forma de evitar esta duplicación de código es hacer que un constructor llame a otro. En este podríamos reescribir el segundo constructor para que llame al primer constructor para que pueda manejar el parámetro de nombre. Para ello, hacemos que el constructor invoque a un segundo constructor de la misma manera que se invoca a un constructor de la  clase base, excepto que utiliza la palabra clave this en lugar de la palabra clave base. 

El siguiente código muestra cómo el segundo constructor de la clase Persona puede invocar a su primer constructor. Se resalta el código que invoca al primer constructor. 

// Constructor con Nombre y Apellido.

Public Persona(String nombre, String apellido)

      :this(nombre)

{

      Apellido = apellido;

}

Nota: Cuando un constructor utiliza la palabra clave this para invocar un segundo constructor en la misma clase, el segundo constructor se ejecuta antes de que se ejecute el cuerpo del primer constructor. 

Si derivamos la clase Empleado de la clase Persona y la clase Empleado incluye una propiedad NombreDepartamento. Es posible que queramos diferentes constructores de empleados que puedan tomar como parámetros nombre, nombre y apellido, o nombre y apellido y nombre de departamento. Estos constructores pueden utilizar la misma técnica que se muestra en esta versión de la clase Persona para hacer que los constructores más complicados invoquen a los más simples. Los constructores Empleado también pueden utilizar la palabra clave base descrita en la sección anterior para invocar a los constructores de la clase Persona. Por ejemplo, el constructor Empleado(nombre, apellido,nombredepartamento) podemos utilizar esta técnica para invocar al constructor Empleado( nombre, apellido) y ese constructor puede utilizar la palabra clave  base para invocar al constructor de Persona(nombre, apellido). 







sábado, 2 de diciembre de 2017

Programación orientada a objetos: conceptos teóricos

Clases


Una clase es un molde que permite definir las características que tomara cada objeto de la clase. Consideremos la clase “coche” como molde de la que luego cada objeto adquiere las características de un coche concreto, por ejemplo micoche. Un coche tiene una serie de atributos que lo convierten en un coche. Cuatro ruedas, un motor, volante, etcétera. También tiene una serie de atributos como el color, el modelo, la marca, etc. Y luego unas funciones como acelerar, frenar, girar. 

En programación orientada a objetos tendríamos sólo la clase coche, y luego cada instancia de la clase (cada objeto) es un coche concreto. Un coche azul modelo A es una instancia concreta de la clase coche.

Una clase tiene variables y métodos. Las variables son las que definen los atributos del objeto en concreto, por ejemplo la variable color es la que define si luego una instancia concreta de coche será de color azul verde o rojo. Y los métodos son los que definen las funciones de la clase. En este caso tendríamos los métodos frenar, acelerar y girar.
Así pues la clase coche tendría las variables: color, cilindrada, marca y modelo. Y los métodos Frenear, acelerar y girar. La clase serían los planos y el código cliente la fábrica de coches de la que van saliendo las instancias  (coches).

Si lo implementamos como una clase real de software convendría que el código de cliente. El que crea las instancias no tuviera acceso directo a las variables de la clase, el color, la marca etc. Para ello se crean las propiedades que son similares a los métodos pero permiten leer y escribir las variables de la clase de una forma controlada por la propia clase y no por el código cliente. De este modo el código de la clase queda fuera de la vista del código cliente (encapsulación) esto permite que a medida que se crean las clases, estas se pueden almacenar en una librería y el programador se centra sólo en el código cliente que utiliza la clase. Una vez probada la clase no hay que volver a tocarla salvo haya que hacer alguna modificación de su funcionalidad. Esto mantiene controlados los cambios, sabemos que si tocamos las facturas no dejarán de funcionar otras partes del programa y podremos centrarnos sólo en probar de nuevo las facturas.




Programación orientada a objetos: conceptos teóricos

sábado, 15 de abril de 2017

Interfaces

Introducción


Un interfaz proporciona una lista de propiedades y métodos que posteriormente serán codificados en una o varias clases. Es decir, su naturaleza es declarativa, no contiene código de los miembros que expresa. En. NET, las interfaces se utilizan comúnmente para prestación de servicios para una clase. La interfaz  apoya algo que puede hacer el objeto de la clase, pero el servicio no está incluido en la relación es-un de la herencia.

Cuando utilizamos la herencia para hacer  nuevas clases diferentes de las clases existentes, si las clases están relacionadas por la herencia, se puede hacer referencia a una instancia derivada a través de una referencia a un valor de la clase base. Este comportamiento polimórfico no se limita a las clases derivadas. Visual Basic. NET ofrece otra construcción: la interfaz, que también se comporta de forma polimórfica

Interfaces con visual basic.NET

sábado, 3 de enero de 2015

Análisis y programación orientados a objetos. Resumen del blog 2014

Como el año pasado, hago balance de lo que ha sido 2014 en el blog. El año comenzó con un resumen del 2013.
  

 Al final no he publicado nada de Java como dije el año pasado y para 2015 creo que tampoco publicaré nada. Este año he tratado temas diversos pues he estado trabajando con varias cosas diferentes. También me he metido más de lleno en .NET y como principiante me han salido algunos errores que he ido resolviendo. He tenido que pasar un proyecto antiguo de Visual Studio 2003 a 2005 así que he puesto algunas cosas interesantes  que encontré.

Análisis y programación orientados a objetos resumen 2014


viernes, 19 de abril de 2013

Principios de la programación orientada a objetos


Clases y Objetos

Se define una clase como un concepto que encapsula las abstracciones de datos y procedimientos que se requieren para describir el contenido y comportamiento de alguna entidad del mundo real. Además este encapsulamiento aísla la clase del resto del código de programa lo que permite ocultar la información que contiene y desacoplar la clase del resto del código del programa. Esto es muy beneficioso pues una vez una clase ha sido implementada y probada podemos desacoplarla del resto del programa haciendo este más sencillo, además de poder reutilizar dicha clase como un módulo en múltiples programas.
Una vez una clase está hecha y probada al programador le basta con saber cómo invocarla y lo que hace esta para poder utilizarla como un módulo separado del resto del programa. Este modo de trabajar permite montar programas como si trabajásemos con ladrillos o bloques de construcción, sin perder el tiempo de redefinir y probar cada ladrillo cada vez que lo necesitamos.
 No hay que olvidar que cada clase en realidad es un patrón o una plantilla que describe una colección de objetos similares y que el objeto concreto será lo que utilizaremos en el código fuente de nuestro programa.
Todos los objetos que genera la clase heredan sus propiedades o atributos y las operaciones o métodos disponibles para la manipulación de estos.
Las clases soportan la herencia por lo que una clase puede tener una o varias clases hijas que heredan las propiedades y métodos de la clase base.
 La mayoría de los objetos físicos tienen características tales como forma, peso, color y tipo de material. Las personas tienen características como fecha de nacimiento, padres, nombre y color de los ojos. Un atributo o propiedad puede verse como una relación binaria entre una clase y su dominio.
La «relación» binaria anteriormente señalada implica que un atributo puede tomar un valor definido por un dominio enumerado. En la mayoría de los casos, un dominio es simplemente un conjunto de valores específicos.
Por ejemplo, la clase Coche tiene una propiedad colorEl dominio de valores de color puede ser (blanco, negro, plata, gris, azul, rojo, amarillo, verde). Pero el dominio también puede ser un conjunto de clases por ejemplo su en vez de Color fuera TipoMotor, en este caso el dominio sería Inyección, Diesel, Gasolina que representa un conjunto de clases que a su vez tiene sus propiedades.

Métodos

Si un método no devuelve un valor como por ejemplo Acelerar, lo llamamosProcedimiento, si por el contrario tiene un valor de retorno por ejemplo CalculaArea lo llamamos Función.
Dentro de una clase nos referimos a ellos como Métodos.
Los métodos son algoritmos que operan con los datos contenidos en las propiedades y representan el comportamiento del objeto.
El disparo de un método en un objeto concreto se llama mensaje y puede ir de algo tan sencillo como devolver el color de una pieza de ajedrez en el objeto Torre de la clase Pieza a algo tan complejo como calcular la declaración de la renta del objeto declaracionClientexx de la clase Renta2013. Este último caso puede implicar la generación de otros mensajes a otros objetos en cascada.
Los mensajes son el medio a través del cual interactúan los objetos. Los métodos son los procedimientos invocados cuando un objeto recibe un mensaje.

Encapsulamiento, herencia y polimorfismo

Como ya se ha dicho anteriormente, la clase encapsula las propiedades y los métodos, quedando estos ocultos al programa principal, lo que reduce la propagación de errores si hay cambios, pues estos son mucho más sencillos de realizar y más localizados. Además si no se toca la clase y está suficientemente probada, se sabe que la clase no contiene los fallos.
La encapsulación facilita la reutilización de código, (componentes). Además las interacciones entre módulos están simplificadas, el objeto llamante sólo debe conocer los parámetros a enviar sin preocuparse de la estructura interna del objeto llamado.
Una Clase hereda todos los atributos de su clase padre, esto quiere decir que todo el código de la clase padre está disponible para la clase hija, no siendo necesario repetirlo de nuevo.
De este modo cualquier cambio en una clase padre se propaga inmediatamente a todas las clases hijas, una clase existente puede sobrescribirse e implementar nuevas versiones de propiedades o métodos para la nueva clase.
El polimorfismo permite utilizar toda la operativa común de una clase y al mismo tiempo dividir las partes que difieren, de tal forma que se reutiliza solamente el código necesario. Así si queremos calcular el área de diferentes formas geométricas podemos definir una clase padre Figura que contenga los atributos y operaciones comunes para todas las figuras y luego crear clases derivadas para cada figura, por ejemplo Cuadrado, Triangulo, Circulo. En la clase base definimos el método calcular área y lo dejamos vacío y luego en cada clase hija definimos el método concreto de cada figura de tal forma que en el código cliente bastará con llamar a
Circulo1.CalcularArea, Cuadrado3.CalcularArea o Triangulo57.CalcularArea sin preocuparnos más, pues cada objeto ya sabe cómo calcular el área correspondiente.
Si hay que añadir una nueva figura apenas hay que tocar código, basta con crear una nueva clase hija y redefinir en ella el método CalcularArea. Sólo tendremos que crear y probar la nueva clase, y si hay fallos sabemos que estarán localizados en la nueva clase y no afectarán a lo anteriormente hecho