Etiquetas

C (31) Cpp (28) Linux (14) asm (8) Telegram (5) bot (5) libreria (5) Algoritmo (3) Errores comunes (3) python (3) Opengl (2) kali (2) Android (1) Snippet (1) nano (1) recursividad (1)

lunes, 25 de marzo de 2024

Arquitectura básica de un Ordenador

/*Este texto no es de mi autoría. Viene de analisisyprogramacionoop.blogspot.com*/ Arquitectura básica de un ordenador Introducción Un ordenador se compone principalmente de un dispositivo de entrada como el teclado y el ratón, otros de salida como la pantalla y un cuerpo central que contiene los periféricos como los puertos USB, salida de impresora, CDs o DVDs y su parte más principal o central, la unidad central de procesamiento o CPU (Central Processing Unit) Esta parte principal del ordenador contiene los controladores para todos estos dispositivos, los cuales todos se nutren o alimentan la CPU que es el núcleo central del ordenador donde se procesa la información y saca el resultado para su interpretación. Aquí me voy a centrar en el funcionamiento esquemático y básico de la CPU y del único lenguaje se sabe interpretar (el código máquina) que manejamos a través del lenguaje ensamblador.
Esto es una CPU
La CPU consiste en el hardware fundamental de un ordenador o cualquier dispositivo programable basado en microprocesador. Se compone fundamentalmente de una unidad de control, una unidad aritmético-lógica ALU y la memoria. La Unidad de Control se encarga de la interpretación y ejecución de las instrucciones y del control de todos los componentes del sistema. La ALU está dedicada a la realización de las operaciones aritméticas y lógicas bajo la supervisión de la Unidad de Control. La Memoria es donde se almacena toda la información, incluyendo ésta, el programa y los datos. Estos tres elementos componen la CPU. La CPU tomada como un conjunto interpreta las instrucciones de un programa a través de la realización de operaciones básicas aritméticas, lógicas y de entrada/salida del sistema. Un ordenador puede tener más de una CPU; esto se llama multiprocesamiento. Todas las CPU modernas están contenidas dentro de microprocesadores, es decir, las contiene un único circuito integrado (o chip). Algunos circuitos integrados (ICs) pueden contener varias CPUs en una única carcasa; estos IC son denominados procesadores multi-núcleo. Los componentes típicos de una CPU son la unidad aritmético lógica (ALU), que como su nombre indica realiza las operaciones aritméticas y lógicas, y la unidad de control (CU), que es la que extrae instrucciones de la memoria, las decodifica y las ejecuta, llamando a la ALU cuando sea necesario. La operación fundamental de la CPU es ejecutar una secuencia de instrucciones almacenadas en la memoria que se llama "programa". El programa consiste en una serie de instrucciones codificadas en números que se almacenan en la memoria. La ejecución de dichas instrucciones de programa se realiza a través de cuatro pasos fundamentales: Fetch (Leer) El primer paso, leer (fetch), consiste en recuperar la instrucción de la memoria de programa. La localización en la memoria de la instrucción a leer en cada momento se determina por el contador de programa (PC), que almacena un número que contiene la dirección de la siguiente instrucción que se debe buscar. Una vez leída la instrucción, el PC se incrementa una o varias unidades de memoria (dependiendo de lo que ocupara la instrucción leída) con el objetivo de apuntar a la siguiente instrucción del programa. Decode (Decodificar) En el paso de decodificación, la instrucción se divide en partes para ser interpretada por el hardware de la CPU. La forma en que la instrucción se interpreta está definida por la arquitectura del conjunto de instrucciones de la CPU. Normalmente la primera parte de la instrucción (opcode) indica lo que se debe hacer y las partes restantes suelen indicar direcciones de memoria operandos o registros en los que realizar la operación especificada en primer término. Execute (ejecución) Diagrama de bloques de una CPU.
Aquí es donde las unidades de la CPU se ponen en marcha para realizar la operación leída. Si, se solicita una operación de adición, entonces los datos contenidos en determinados registros pasan a través de la unidad aritmético lógica (ALU) la cual deposita el resultado en un registro especial llamado acumulador (por que se suma el resultado a contenido que tuviera). Dicha ALU solo puede sumar o realizar operaciones lógicas de bits. Si la operación produce un resultado demasiado grande para el tamaño del acumulador, activa una bit de desbordamiento aritmético localizado en un registro de banderas (flags) Writeback (escribir) El paso final, la escritura (writeback), simplemente "escribe" los resultados de la ejecución a una o varias posiciones de memoria aunque a menudo, los resultados son escritos en algún registro interno de la CPU para que tenga un acceso rápido por las siguientes instrucciones. Existen instrucciones que manipulan el contador de programa. Éste tipo de instrucción se llama "salto" (jumps) y se utilizan para generar comportamientos como bucles (loops), o llamadas a subrutinas (pequeños programas completos que se ejecutan cuando son llamados desde el programa principal). Si la instrucción ejecutada es un salto, el contador de programa será modificado para contener la dirección de la instrucción a la cual saltó. Esto obliga a almacenar la dirección siguiente de programa original en unos registros especiales llamados “pila” stack que serán leídos cuando finalice la ejecución del subprograma o salto para poder continuar por la dirección correspondiente del programa principal Reloj La mayoría de las CPU operan en función de una señal de sincronización. Esta señal, se denomina señal de reloj, y tiene la forma de una onda cuadrada periódica. Toma un valor alto (una tensión eléctrica determinada) durante un tiempo y luego cae bruscamente a cero donde se mantiene el mismo tiempo hasta subir de nuevo al valor alto bruscamente. El período que lleva el cambio de la señal de reloj debe ser más largo que el tiempo que emplea una señal en propagarse en el peor de los casos. La señal del reloj cambia constantemente, provocando la conmutación de muchos componentes (cambio de estado). Esta señal es la que utiliza la CPU para realizar todas sus operaciones de lectura y escritura en memoria o en registros, ejecución, y cualquier otra operación de control de cualquier dispositivo de la CPU. La velocidad de un procesador depende entre muchos otros factores de la velocidad del reloj (generalmente en múltiplos de hertzio) y las instrucciones por ciclo de reloj (IPC), que juntos son los factores que determinan el número de instrucciones por segundo (IPS) que la CPU puede ejecutar. Unidad Aritmético Lógica (ALU) Un típico símbolo esquemático para una ALU: En el acumulador y el registro actúan como operandos; La salida se graba en el acumulador; A es la entrada de la unidad de control; B es un estado de la salida.
La unidad aritmético lógica, conocida como ALU (arithmetic logic unit), es el circuito digital central de la CPU y su objetivo es realizar las operaciones aritméticas suma y operaciones lógicas entre dos números. Los grandes ordenadores o mainframes modernos continenen multitud de microprocesadores a su vez con múltiples núcleos, y cada núcleo con múltiples unidades de ejecución, cada una de ellas con múltiples ALU. Muchos otros circuitos pueden contener en el interior una unidad aritmético lógica. Esquema simplificado.
Esquema de una ALU según wikipedia.
Una ALU simple de 2 bits que hace operaciones de AND, OR, XOR y adición (ver explicación en el texto). La ALU se compone básicamente de un Circuito Operacional, Registros de Entradas, un acumulador que como se ha dicho anteriormente es un registro especial donde se deposita la salida de la ALU y un Registro de Estados. La mayoría de las acciones de un ordenador son realizadas por la ALU. Una unidad de control controla la ALU, al ajustar los circuitos que le indican qué operaciones realizar. Descripción del esquema simplificado. En la imagen se muestra una ALU de 2 bits con dos registros de entrada (operandos) llamadas A y B: A0 y B0 corresponden al bit menos significativo y A1 y B] corresponden al bit más significativo. Cada bit de la ALU se procesa de manera idéntica, con la excepción del direccionamiento del bit de acarreo. Las entradas A y B van hacia las puertas lógicas de la izquierda, de arriba a abajo, XOR, AND, OR. Las tres primeras puertas realizan las operaciones XOR, AND, y OR sobre los datos A y B. La última puerta XOR es la puerta inicial de un sumador completo. El paso final de las operaciones sobre cada bit es la multiplexación de los datos. La entrada OP de 3 bits, OP[0], OP[1] y OP[2] (desde la unidad de control) determina que función se va a realizar: OP = 000 → XOR OP = 001 → AND OP = 010 → OR OP = 011 → Adición El resto de entradas del multiplexor está libre para otras operaciones (resta, multiplicación, división, NOT A, NOT B, etc.) Aunque OP[2] actualmente no es utilizada en este montaje (a pesar de estar conectada), sería usada para realizar otras operaciones aparte de las 4 operaciones ya comentadas. Los datos de acarreo de entrada y acarreo de salida, llamados flags (banderas), son típicamente conectados a algún tipo de registro de estado. Entradas y salidas Las entradas a la ALU son los datos sobre los cuales se realizarán las operaciones (operandos) y un código desde la unidad de control que indica qué operación se realizará. Su salida es el resultado de la operación. La ALU también lee o genera un conjunto de códigos de condición desde o hacia un registro de estado. Estos códigos se utilizan para indicar casos como acarreo entrante o saliente, desbordamiento , división por cero, etc. ALU y FPU Una unidad de coma flotante, FPU (Floating Point Unit ), realiza operaciones aritméticas entre dos valores igual que la ALU, pero esta lo realiza para números en representados en formato de coma flotante, que es mucho más compleja que la usada en una ALU. Para hacer estos cálculos, la FPU lleva varios circuitos complejos, incluyendo ALUs internas.

Ensamblador y Arquitectura de Procesadores II

/*Este texto no es de mi autoría. Viene de analisisyprogramacionoop.blogspot.com*/ Registros Los procesadores de 64 bits disponen de una serie de registros formada por registros de propósito general y registros específicos. Los registros de propósito son 16 de 64 bits y 6 registros específicos con segmento de 16 bits, también dispone de un registro de estado de 64 bits (RFLAGS) y de un registro contador de programa de 64 bits (RIP). Registros de propósito general Consta de 16 registros de datos de 64 bits (8 bytes): RAX, RBX, RCX, RDX, RSI, RDI, RBP, RSP y R8-R15. Los 8 primeros registros se nombran de forma parecida a los 8 registros de propósito general de 32 bits disponibles en la arquitectura de 32 bits (EAX, EBX, ECX, EDX, ESI, EDI, EBP y ESP). Los registros se pueden acceder de cuatro formas diferentes: -Como registros de 64 bits (quad word). -Como registros de 32 bits (double word), se accede a los 32 bits de peso menor. -Como registros de 16 bits (word), se accede a los 16 bits de peso menor. -Como registros de 8 bits (byte), accediendo individualmente a uno o dos de los bytes de menor peso según el registro. El acceso a registros de byte tiene ciertas limitaciones según el registro. La nomenclatura que se utiliza según si se quiere acceder a registros de 8, 16, 32 o 64 bits y según el registro se muestra en la figura siguiente:
Existen limitaciones en el uso de registros de propósito general: -En una misma instrucción no se puede usar un registro del grupo AH, BH, CH, DH junto con cualquiera del grupo SIL, DIL, BPL, SPL, R8B – R15B. -Registro RSP: posee una función especial, es el apuntador de pila, contiene siempre la dirección del primer elemento de la pila. No es posible utilizarlo con otra finalidad, pues perderíamos el acceso a la pila. -Cuando se utiliza un registro de 32 bits como operando destino de una instrucción, la parte alta del registro se fija a 0. Registros de propósito específico Existen varios registros de propósito específico: Registros de segmento: Hay 6 registros de segmento de 16 bits. - CS: code segment - DS: data segment - SS: stack segment - ES: extra segment - FS: extra segment - GS: extra segment Estos registros son usados en modelos de memoria segmentados (heredados de la arquitectura de 32 bits). En estos modelos, la memoria se divide en segmentos, de forma que en un momento dado el procesador solo puede acceder a seis segmentos de memoria usando cada uno de los seis registros de segmento. En el modo de 64 de bits, estos registros apenas se utilizan, pues se trabaja con un modelo de memoria lineal y el valor de estos registros se establece en 0 (excepto para los registros FS y GS, que pueden ser usados como registros base en el cálculo de direcciones). Registro de instrucción o instruction pointer (RIP): es el registro contador de programa (PC) y contiene la dirección efectiva (o dirección lineal) de 64 bits de la instrucción siguiente que se ha de ejecutar. Cada vez que se lee la siguiente instrucción de la memoria, este registro se actualiza con la dirección de la instrucción siguiente que se tiene que ejecutar; también se puede modificar el contenido de este registro durante la ejecución de una instrucción de ruptura de secuencia (una llamada a una subrutina, o bien a través de un salto condicional o incondicional). Registro de estado o Flags register (RFLAGS): este registro posee información sobre el estado interno del procesador e información sobre el resultado de la ejecución de las instrucciones, es también de 64 bits. Pero sólo se usa la parte baja del registro (bits de 31 a 0), que corresponde al registro EFLAGS de la arquitectura de 32 bits. La parte alta no se utiliza. El registro de estado se utiliza para consultar el valor individual de cada uno de sus bits; eso se realiza a través de instrucciones específicas, como las instrucciones de salto condicional que consultan uno o más bits para determinar si saltan o no según el estado de alguno de estos bits. La última instrucción que los ha modificado no tiene por qué ser la última instrucción que se haya ejecutado.
A continuación se muestra una tabla con el significado de los bits de este registro.
Modo extendido de 64 bits El modo extendido de 64 bits es el modo que utilizan los sistemas operativos de 64 bits. Este modo general dispone de un modo de operación de 64 bits y un modo de compatibilidad con los modos de operación anteriores de las arquitecturas de 16 y 32 bits. En un sistema operativo de 64 bits, los programas de 64 bits se ejecutan en modo de 64 bits y las aplicaciones de 16 y 32 bits se ejecutan en modo de compatibilidad. Los programas de 16 y 32 bits que se tengan que ejecutar en modo real o virtual x86 no se podrán ejecutar en modo extendido a no ser que sean emulados. Modo de 64 bits El modo de 64 bits permite el acceso a 16 registros generales de 64 bits cada uno. En este modo se utilizan direcciones virtuales (o lineales) que por defecto son de 64 bits y también permite acceder a un espacio de memoria lineal de 264 bytes. El tamaño por defecto de los registros operadores se mantiene en 32 bits para la mayor parte de las instrucciones. Se permite cambiar este tamaño por defecto de forma individual en cada instrucción a través de modificadores. Por otra parte permite el direccionamiento relativo al PC (RIP en esta arquitectura) en el acceso a los datos de cualquier instrucción. Modo de compatibilidad Este modo permite a un sistema operativo de 64 bits ejecutar directamente aplicaciones de 16 y 32 bits sin tener que recompilarlas. En este modo, las aplicaciones utilizan direcciones de 16 y 32 bits, y tienen acceso a un espacio de memoria de 4 Gb. El tamaño de los operandos puede ser de 16 o 32 bits. Las aplicaciones, lo ven como si se estuviera trabajando en modo protegido dentro del modo heredado. Modo heredado de 16 y 32 bits El modo heredado de 16 y 32 bits lo utilizan los sistemas operativos de 16 y 32 bits. Cuando el sistema operativo utiliza estos modos de 16 bits o de 32 bits, el procesador actúa como un procesador x86 y solo se puede ejecutar código de 16 o 32 bits. Este modo solo permite utilizar direcciones de 32 bits, de este modo, se limita el espacio de direcciones virtual a 4 GB. Dentro de este modo general hay tres modos: Modo real. Implementa el modo de programación del microprocesador Intel 8086, pero con la capacidad de permitir pasar al modo protegido o al modo de gestión del sistema. El procesador se inicia en modo real al arrancar el sistema y cuando se reinicia. Es el único modo de operación que permite utilizar un sistema operativo de 16 bits. El modo real dispone de un espacio de memoria de 1 MB con direcciones de memoria de 20 bits y con acceso a direcciones hardware (como el sistema de E/S). No proporciona protección de memoria en sistemas multitarea ni de código con diferentes niveles de privilegio. Modo protegido. Es el modo por defecto del procesador. Puede usar características como memoria virtual, paginación o multitarea. Las capacidades de este modo incluyen la posibilidad de ejecutar código en modo real, modo virtual-8086, en cualquier tarea en ejecución. Modo virtual 8086. Posibilita ejecutar programas de 16 bits como si fueran tareas dentro del modo protegido. Modo de gestión de sistema Este modo, también llamado system management mode (SMM) consiste en un modo de operación transparente del software convencional (sistema operativo y aplicaciones). Consiste en la suspensión de la ejecución normal (incluido el sistema operativo) y se ejecuta un software especial con grandes niveles de privilegios, diseñado específicamente para controlar el sistema. Las tareas habituales de este modo, son tales como la gestión de energía, la depuración asistida por hardware, ejecución de microhardware (software asistido por hardware). Este modo es el que utiliza la BIOS y los controladores de dispositivo de bajo nivel. Se accede al SMM a través de una interrupción de gestión del sistema (SMI, system management interrupt). Este tipo de peticiones se generan con acontecimientos independientes o pueden ser disparadas a través del software del sistema al acceder a una dirección de E/S considerada especial por la lógica de control del sistema.

Ensamblador y Arquitectura de Procesadores

Descripción de la arquitectura de 64 bits Introducción En una entrada anterior hacía una descripción general de la arquitectura de un ordenador, en esta entrada voy a afinar un poco y voy a hacer una breve visión de la arquitectura de 64 bits también conocida como x86-64 porque se trata de una ampliación de la arquitectura x86. La arquitectura x86 comenzó con Intel con el procesador Intel 8086 en el año 1978 como arquitectura de 16 bits. Después esta arquitectura evolucionó hasta una arquitectura de 32 bits cuando apareció el procesador Intel 80386 en el año 1985, denominada i386 o x86-32. AMD amplió esta arquitectura de 32 bits de Intel hasta una de 64 bits y la llamó x86-64. Intel pronto adoptó las extensiones de la arquitectura de AMD bajo el nombre Intel 64.
Con el procesador Itanium, Intel lanzó la arquitectura denominada IA-64, derivada de la IA-32 y que no es compatible con las arquitecturas x86, x86-32 o x86-64. La arquitectura IA-64 se originó en Hewlett-Packard (HP) y más tarde fue desarrollada con Intel para utilizarse en sistemas de alto rendimiento. Modos de operación Los procesadores con arquitectura x86-64 deben mantener la compatibilidad con los procesadores de 32 bits por eso presentan los mismos modos de operación lo que permite ejecutar aplicaciones de 16 y 32 bits, por otra parte incluyen un modo nuevo llamado modo extendido en el que es posible trabajar en modo real de 64 bits. Además de los múltiples modos de operación con los que puede contar un microprocesador, existen dos modos fundamentales que todo microprocesador debe tener: El modo supervisor y el modo protegido. El modo supervisor Es el que utilizar el núcleo del sistema para ejecutar tareas de bajo nivel que precisan de un acceso sin restricciones al hardware, suelen ser tareas como el control de la memoria o la comunicación con otros dispositivos. El modo protegido Se utiliza para casi todo el resto de las tareas. Al ejecutar programas en modo protegido utilizaremos el hardware haciendo llamadas al sistema operativo, que a su vez es el que lo controla en modo supervisor. Puede haber otros modos similares al protegido, por ejemplo el modo virtual se utiliza para emular otros procesadores de la misma familia, y de este modo mantiene la compatibilidad con procesadores anteriores. Con el procesador Itanium, Intel lanzó la arquitectura denominada IA-64, derivada de la IA-32 y que no es compatible con las arquitecturas x86, x86-32 o x86-64. La arquitectura IA-64 se originó en Hewlett-Packard (HP) y más tarde fue desarrollada con Intel para utilizarse en sistemas de alto rendimiento. Modos de operación Los procesadores con arquitectura x86-64 deben mantener la compatibilidad con los procesadores de 32 bits por eso presentan los mismos modos de operación lo que permite ejecutar aplicaciones de 16 y 32 bits, por otra parte incluyen un modo nuevo llamado modo extendido en el que es posible trabajar en modo real de 64 bits. Además de los múltiples modos de operación con los que puede contar un microprocesador, existen dos modos fundamentales que todo microprocesador debe tener: El modo supervisor y el modo protegido. El modo supervisor Es el que utilizar el núcleo del sistema para ejecutar tareas de bajo nivel que precisan de un acceso sin restricciones al hardware, suelen ser tareas como el control de la memoria o la comunicación con otros dispositivos. El modo protegido Se utiliza para casi todo el resto de las tareas. Al ejecutar programas en modo protegido utilizaremos el hardware haciendo llamadas al sistema operativo, que a su vez es el que lo controla en modo supervisor. Puede haber otros modos similares al protegido, por ejemplo el modo virtual se utiliza para emular otros procesadores de la misma familia, y de este modo mantiene la compatibilidad con procesadores anteriores. Cuando se enciende un equipo, se ejecutan los programas de la BIOS que tienen acceso ilimitado al hardware en modo, una vez iniciado el sistema operativo, se pasa el control a otros programas con lo que el procesador se pone ya en modo protegido. En modo protegido, los programas pueden acceder a un conjunto de instrucciones más limitado, sólo podrán abandonar el modo protegido realizando una petición de interrupción que devuelva el control al sistema operativo; de este modo se garantiza el control para acceder al hardware.
El modo de 64 bits Los elementos que son visibles desde el punto de vista del programador son los siguientes: Espacio de memoria: un programa trabajando este modo tiene acceso a un espacio de direcciones de 264 bytes. El espacio real que puede gestionar el procesador depende de la implementación de la arquitectura. Registros: suelen consistir en 16 registros de propósito general de 64 bits cada uno, y permiten operaciones de byte (8 bits), palabra (16 bits), palabra doble (32 bits) y palabra cuadruple (64 bits). Además dispone de un registro contador de programa (RIP, instruction pointer register) de 64 bits. El registro de bits de estado también es de 64 bits (RFLAGS). Los 32 bits de la parte alta están reservados y son inaccesibles; los 32 bits de la parte baja son accesibles y corresponden a los mismos bits que una arquitectura de 32 bits. (registro EFLAGS).
Organización de la memoria El procesador lee la memoria usando direcciones físicas de memoria. El tamaño físico de la memoria accesible para los procesadores depende de la implementación: supera los 4 Gbytes, pero es inferior a los 264 bytes posibles. En el modo de 64 bits, la arquitectura permite un espacio de direcciones virtual o lineal de 64 bits (direcciones de 0 a 264 – 1), pero el espacio de direcciones físico es inferior al espacio de direcciones lineal, esto hace necesario un mecanismo de correspondencia entre las direcciones lineales y las direcciones físicas que llamaremos mecanismo de paginación. Paginación Este mecanismo lo gestiona el hardware del procesador y el sistema operativo. Las direcciones virtuales son traducidas a direcciones físicas de memoria utilizando un sistema jerárquico de tablas de traducción gestionadas por el software del sistema (sistema operativo). Una dirección virtual se divide en campos, y cada campo se comporta como un índice dentro de una de las tablas de traducción. Cada uno de estos valores en la posición indexada actuará como una dirección base de la tabla de traducción siguiente.
Orden de los bytes Los procesadores 64 bits utilizan un sistema de ordenación de los bytes cuando se accede a los datos que se encuentran almacenados en la memoria. En concreto, se utiliza un sistema en el cual el byte de menos peso de un dato ocupa la dirección más baja de memoria (little-endian). Los registros también utilizan el modelo little-endian y por este motivo el byte menos significativo de un registro se denomina byte 0.
Tamaño de las direcciones Los programas que son ejecutados en modo de 64 bits generan directamente direcciones de 64 bits. Modo compatibilidad Los programas que se ejecutan en el modo compatibilidad generan direcciones de 32 bits. Estas direcciones se extienden a 64 bits añadiendo ceros a los 32 bits más significativos de la dirección. Este proceso es gestionado por el hardware del procesador. Tamaño de los desplazamientos y de los valores inmediatos En el modo de 64 bits las instrucciones de desplazamiento de los direccionamientos relativos y los valores inmediatos es de 32 bits excepto la instrucción MOV que permite cargar un valor inmediato de 64 bits.

Escribir programa Orientado a Objetos II

/*Este texto no es de mi autoría. Pertenece al blog analisisyprogramacionoop*/ Esto es una continuación del artículo anterior sobre como Crear un primer programa orientado a objetos sencillo. En este artículo aprenderemos a § Usar una clase en una aplicación. § Usar las herramientas de Microsoft Visual Studio .NET para crear la definición de una clase Uso la clase CHospital en una aplicación Como se ha dicho anteriormente una clase es una plantilla de un objeto. Por ejemplo un coche genérico es una clase, mientras que un coche concreto es un objeto (instancia de la clase). Para poner los datos en los campos y propiedades, hay que crear una instancia de la clase en la memoria, esta acción se conoce como instanciación. Cuando se crea una instancia, se reserva una sección de memoria para mantener los campos del objeto. Si se crea otra instancia de la clase, se reserva otra sección de la memoria para sus campos. Por ejemplo podemos tener n instancias de la clase coche y cada una de ellas representará un coche concreto con sus atributos particulares (propiedades) marca, modelo, color, etc. Vamos a crear dos instancias de la clase CHospital en el proyecto Hospital, y se mostrarán los datos de cada hospital, así que tendrán que crearse dos instancias por separado de la clase CHospital. En lugar de crear una interfaz elegante, se escribirá sólo el suficiente código para ver si la clase está trabajando como se esperaba. Driver de Pruebas La creación de un pequeño programa para probar una clase se llama Driver. Es una buena idea probar la clase un poco con el Driver antes de agregarla a un programa más amplio. Se utiliza el Driver para probar la clase sin la interferencia del resto del código del programa. Crear una instancia de CHospital 1. En el Explorador de soluciones, hacer doble clic en Form1 para abrirlo en el Windows Diseñador de formularios. Si Form1 se abre en el editor de código, seleccionar Ver Diseñador. Crear un entorno visual similar al mostrado a continuación
2. Agregar el siguiente código para el evento SelectedIndexChanged del combo superior Private Sub CboHospitales_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CboHospitales.SelectedIndexChanged Dim Hospital1_grupo As CHospital Hospital1_grupo = New CHospital() End Sub 3. Agregar el código siguiente para establecer las propiedades del hospital inmediatamente después del código introducido en el paso 2: Hospital1_grupo.Telefono = "914567894" Hospital1_grupo.Direccion = "Recoletos 23" Hospital1_grupo.NumSalas = 28 Cuando se crea la instancia de CHospital , sus campos contienen los valores especificados en la definición de clase. Los campos de dirección y teléfono son una cadena vacía, el número de salas es 0. Tener en cuenta que no hay diferencia en el código del cliente si se utiliza un campo o una propiedad. 4. Agregar el código siguiente para crear otra instancia de la clase CHospital. Dim Hospital2_grupo As CHospital = New CHospital() Hospital2_grupo.Telefono = "912346578". Hospital2_grupo.Direccion = "Bravo Murillo 324" Hospital2_grupo.NumSalas = 12 En este caso, se utiliza una sintaxis diferente para declarar e inicializar una variable de la Clase CHospital. Visual Basic permite la declaración y la inicialización en la misma declaración. La declaración e iniciación en la misma sentencia tiene las siguientes ventajas: § Los programadores tienen menos probabilidades de olvidarse de inicializar la variable. § Cuando una clase define un constructor con parámetros, los campos se pueden inicializar al mismo tiempo. Usar una instancia de la Clase CHospital 5. Agregar el código siguiente para mostrar algunos de los textos de los dos libros. Dim Informe As String Informe = "Hospital de " & Hospital1_grupo.Direccion & "Con Telefono" & Hospital1_grupo.Telefono & "Tiene" & Hospital1_grupo.NumSalas & "Salas" MessageBox.Show(Informe) Informe = "Hospital de " & Hospital2_grupo.Direccion & "Con Telefono" & Hospital2_grupo.Telefono & "Tiene" & Hospital2_grupo.NumSalas & "Salas" MessageBox.Show(Informe) En este fragmento de código se puede ver que hay dos instancias independientes de la clase CHospital. Es posible hacer referencia a estas instancias utilizando las variables Hospital1_grupo y Hospital2_grupo. El concepto orientado a objetos permite que cada instancia pueda ser referenciada por separado y se conoce como identidad. Esto no significa que haya que crear una variable para cada instancia. La creación de tantas variables es difícil de manejar si se necesitan cientos de instancias de una clase. Identidad significa que se puede hacer referencia a cada instancia por separado cuando sea necesario. Al crear una instancia CHospital, los campos de Hospital1_grupo han cambiado y se ha llamado al método AltaMedicoHos. Más tarde se ha recuperado el valor de la propiedad Direccion. El valor de la dirección se ha mantenido sin cambios después de llamar al método AltaMedicoHos. El hecho de que el valor se mantuviera sin cambios demuestra el concepto de estado de los objetos, la idea de que los campos conservan su valores entre llamadas a métodos. Se puede comparar la forma en como funciona el método AltaMedicoHos, un método tiene las declaraciones de las variables. Después de que el método AltaMedicoHos termina, las variables salen de ámbito y se pierden sus valores. 6. Presionamos F5 para ejecutar el código. Al hacer clic en el botón Mostrar página. Los resultados se muestran aquí:
Al hacer clic en Aceptar y, a los títulos de los libros se muestran en un cuadro de mensaje, como se muestra aquí: Hacer clic en Aceptar y, a continuación, cerrar la aplicación. Hemos creado una clase, CHospital, y dos instancias de la misma. Cómo usar el visor de Clases El entorno de programación permite obtener una vista del árbol de la estructura de clases del proyecto, los espacios de nombres y clases. La Vista de clases puede compartir la misma ventana que el Explorador de soluciones. En el menú Ver, hacer clic en Vista de clases para abrir la Vista de clases. La Vista de clases ampliado se muestra a continuación.
El nodo de más alto nivel representa el proyecto, Hospital. El siguiente nivel de nodos representa los espacios de nombres en el proyecto. Un proyecto puede contener varios espacios de nombres, en este caso, sólo hay uno. El espacio de nombres del proyecto consta de tres clases: la clase que hemos creado, CHospital, otra que crearemos posteriormente CPersona y la clase para el formulario Windows Forms, frmPrincipal. La clase CHospital contiene cuatro campos privados, representados por bloques de color azul con un candado. La clase también contiene las cuatro respectivas propiedades. Representadas por una mano sosteniendo un formulario. Además, la clase contiene un método, AltaMedicoHos con dos parámetros objeto que devuelven un booleano. El método está representado por un bloque de color púrpura. Todas las clases en Visual Basic son implícitamente un objeto de una clase base Añadir el método UbicarPaciente a la clase CHospital 1. Añadir el siguiente código a la clase CHospital: Esto crea un array de códigos de Sala para el hospital y su propiedad para acceder a él. Private m_salas() As String Public Property Sala(ByVal i As Integer) As Integer Get Return m_salas(i) End Get Set(ByVal value As Integer) m_salas(i) = value End Set End Property Public Function UbicarPaciente(ByVal Nom_Paciente As CPersona, ByVal Cod_Sala As CHospital, ByVal i As Integer) As Boolean Dim Reg As RDO.rdoResultset Dim strSQL As String Reg = Nothing On Error GoTo Errores_UbicarPaciente strSQL = "INSERT INTO dbo.tbPacSal (strId_PAC,strID_SAL) VALUES (" & Nom_Paciente.Codigo & "," & Cod_Sala.Sala(i) & ")" glbBaseDatos.Execute(strSQL) Reg.Close() Return True Errores_UbicarPaciente: Return False End Function Crear el programa Hospital Ahora es el momento de escribir el código y probar la aplicación completa. Conectar a la base de datos el combo box para mostrar el campo strNombre de TbHospital Resumen Para Crear una instancia de una clase Inicializar la variable usando la palabra new Dim Hospital1 as New CHospital() Establecer una propiedad de la instancia Dim Hospital1 as New CHospital() Hospital1.Salas = 25 Llamar a un método de la clase. Dim Hospital1 as New CHospital() Dim Num_Sala As String Num_Sala = Hospital1.Sala(3)

Escribir programa Orientado a Objetos I

/*Este texto no es de mi autoría. Viene del blog analisisyprogramacionoop*/ Escribir un programa orientado a objetos (I) Se trata de una serie de artículos prácticos para crear un primer Programa Orientado a Objetos con Visual Basic .Net se comienza con un programa sencillo y se le van añadiendo complejidad con nuevos elementos. Con este artículo aprenderemos a: Decidir las clases que debe tener el programa. Crear una clase con variables, propiedades y métodos. Los bloques principales de un programa orientado a objetos son las clases, un objeto es una ocurrencia concreta de una clase (un coche concreto es una ocurrencia concreta de la clase coche genérica). Un objeto al ser concreto toma atributos concretos definidos en sus propiedades (en un coche sería el color, modelo, etc.) y métodos que son las acciones que tienen permitido hacer (en un coche los métodos serían acelerar, frenar, girar). Diseñaremos e implementaremos las clases usando propiedades y métodos. A continuación, declararemos e inicializaremos las variables de las clases. Por último, implementaremos una solución llamando a los métodos, propiedades y a las variables de la clase. Hospital: Un primer Programa Orientado a Objetos En la construcción de un sistema de información para el control hospitalario se revelaron los siguientes conceptos: - Hospital: con los datos, Nombre, Dirección y Teléfono - Sala: con los datos, Número y Cantidad de camas - Médico: con los datos, Identidad, Nombre y Especialidad - Paciente: con los datos, Identidad, Nombre, Dirección y Fecha de nacimiento. Por otra parte, las relaciones reveladas entre dichos conceptos son: -Cada hospital tiene varias salas. Todas y cada una de ellas pertenecen a un hospital (y sólo a uno). -Cada médico trabaja en un único hospital, todo hospital tiene al menos 10 médicos. -Un paciente puede estar internado; si lo está, estará en una sala y sólo en una. -La capacidad máxima de camas que puede tener una sala es de cinco pacientes. -Cada paciente puede ser atendido por más de un médico (pero por lo menos por uno) y a su vez un médico puede atender a varios pacientes. Se trata de implementar un programa que permita la gestión de un grupo de hospitales. El programa tendría varias pestañas para añadir/cambiar/eliminar los datos correspondientes, la pestaña paciente sería la más compleja y sería de este tipo:
Diseño de las clases Para encontrar las clases que se necesitan, hay que definir los objetos que usaremos, así como las propiedades de estos objetos y los métodos de comportamiento de estos objetos. Hay muchas formas de diseñar clases, aquí se inicia con un análisis del texto del problema. Los nombres son seleccionados como candidatos para las clases, mientras que los verbos se convierten en candidatos para los métodos. En el curso del análisis, se eliminarán muchos de los nombres de los candidatos, y se pueden descubrir clases que no se encuentran entre los nombres de la especificación. Después de determinar los objetos, propiedades y métodos que pertenecen a sus clases, a continuación, se puede entonces escribir especificación de la clase que se va a utilizar en la ejecución. Búsqueda de Clases Dado un enunciado, buscar los Nombres del enunciado para encontrar las Clases. Por ejemplo: Se genera en el ordenador un programa que gestione un grupo de hospitales en el que se debe definir que médico trabaja en cada hospital y que pacientes atiende. También se necesita saber en que sala de que hospital se ubica cada paciente. Los médicos atenderán a los pacientes en función de su especialidad y de la dolencia del paciente. Hay que gestionar las altas y bajas de los pacientes, así como la sala y médicos asignados. Por motivos obvios descartamos las clases ordenador y programa, quedando hospital, médico, paciente, sala, especialidad y dolencia. Especialidad y dolencia son atributos de médico y paciente, por lo que los dejamos como propiedades de sus respectivas clases. Búsqueda de Propiedades y Métodos Para buscar los métodos se buscan los verbos en el enunciado: Se genera en el ordenador un programa que gestione un grupo de hospitales en el que se debe definir que médico trabaja en cada hospital y que pacientes atiende. También se necesita saber en que sala de que hospital se ubica cada paciente. Los médicos atenderán a los pacientes en función de su especialidad y de la dolencia del paciente. Hay que gestionar las altas y bajas de los pacientes, así como la sala y médicos asignados. Generar no es relevante, gestionar y definir tampoco. Trabaja y Atiende son métodos del Médico, saber es irrelevante. Ubicar (un paciente) es un método del hospital, Atendido por (un médico) parece razonable incluirlo como un método del hospital más que del Médico. Trabaja en (un hospital) también parece referido al hospital. Por lo que parece evidente que tendremos una clase CHospital. Tanto pacientes como médicos son personas con atributos muy similares, por lo que se puede optar por fusionarlos en una única clase CPersona que distinga si en Médico o no con un atributo booleano Finalmente se revisa de nuevo el enunciado para ver si las clases y los métodos hacen lo que les pedimos y se ordenan en una tabla. Clase Propiedades Métodos CHospital Salas Teléfono Direccion AltaMedicoHos BajaMedicoHos UbicarPaciente CPersona DNI Fecha_Nacimiento Direccion Dolencia/Especialidad Medico Alta Baja AsignarMedicoPac El objetivo es que la mayor parte de la implementación de una clase sea invisible al usuario externo, es decir que sea privada en la mayor medida posible para que el usuario la utilice como una caja cerrada. (Cuando nos referimos al usuario no nos referimos al usuario de la aplicación sino al usuario del código, es decir al desarrollador que utilizará luego estas clases para implementar la funcionalidad de la aplicación) Para construir código como una caja cerrada, en vez de definir las variables como públicas, se crean como variables privadas y luego se crea una propiedad por cada variable para acceder a ella desde el exterior sin tocarla en la clase. Por ejemplo, puedo acceder a m_telefono desde el exterior a través de este código: Private m_telefono as string <- Variable Public Property Telefono() As String <- Propiedad Get Return (m_telefono) End Get Set(ByVal value As String) m_telefono = value End Set End Property El orden en el que deben aparecer en una clase es: Declaraciones de los campos Constructores Propiedades Métodos. Probar el diseño de la clase Conviene leer de nuevo el enunciado para determinar si las clases, sus propiedades y sus métodos se ajustan a la funcionalidad necesaria para resolver el problema. Clases Propiedades y Métodos ---------------------------------------------------------------------- Clase CHospital Propiedades: Dim num_salas as integer Dim direccion as string Dim telefono as string Métodos: AltaMedicoHos BajaMedicoHos UbicarPaciente ---------------------------------------------------------------------- Clase CPersona Propiedades: Dim DNI as string Dim Fecha_Nacimiento as date Dim Direccion as string Dim Dolen_Espec as string Dim Medico as boolean Métodos: Alta Baja AsignarMedicoPac ---------------------------------------------------------------------- Crear la Clase CHospital El siguiente ejercicio cubre los conceptos básicos de la implementación de la clase con la clase CHospital como ejemplo. Para implementar la biblioteca de clases, vamos a usar algunas de las herramientas de desarrollo proporcionado por Microsoft Visual Studio. En el entorno de desarrollo integrado (IDE). 1. En el IDE, hacer clic en el menú Archivo, seleccionar Nuevo y, a continuación, hacer clic en Proyecto. El cuadro de diálogo Nuevo proyecto se abre.
2. Seleccionar Proyectos de Visual Basic en el árbol tipos de proyecto (1), hacer clic en aplicación para Windows (2) en la lista de plantillas.
3. Introducir Hospital en el cuadro Nombre y hacer clic en Aceptar. 4. Mostrar el Explorador de soluciones, seleccionar el Explorador de soluciones en la vista del menú.
5. Hacer clic en el proyecto Hospital en el Explorador de soluciones. Botón derecho del ratón y añadir (add), y nuevo objeto (new item).
6. Elegir Class y Teclear CHospital.vb en el cuadro Nombre, tener en cuenta que el nombre de clase se inicia con una mayúscula y se escribe en singular. 7. Hacer clic en Añadir (Add). El IDE agrega un archivo a su proyecto. El archivo incluye la definición básica de una clase, como se muestra en la pantalla siguiente.
La clase de Visual Basic contiene el mínimo para una declaración de clase. Ésta es la sintaxis para la declaración de una clase en Visual Basic: Class NombreClase End Class En este caso, la clase se denomina “CHospital”. El IDE agrega el modificador público que se muestra e indica que la clase se puede utilizar durante todo el proyecto Añadir los campos NumSalas, Telefono y Direccion a la clase Un campo es una variable declarada en un bloque de clase. Los campos pueden ser de cualquier tipo de .NET tal como entero o booleano, etc;. O de una clase de .NET, como de tipo TextBox o ListBox, o cualquier otra clase que se haya creado. 1. Localizar el principio de la definición de clase. En Visual Basic, la definición de clase se inicia inmediatamente después de la línea que muestra el nombre de la clase. 2. Agregar el siguiente código dentro de la clase para crear los campos Salas, Teléfono y Dirección. Public NumSalas As Integer = 0 Public Telefono As string = "" Public Direccion as string = "" Sugerencia. Por convención, las letras iniciales de los nombres de los miembros públicos (campos, propiedades, métodos y eventos) de una clase se capitalizan (Campotexto) o se intercapitalizan (CampoTexto). De acuerdo con el código, que se ha especificado, los valores iniciales de los campos: cero para el campo entero NumSalas, y cadena vacía para los campos de cadena de texto Telefono y Direccion. Un principio básico de programación orientada a objetos es que un objeto debe mantenerse en un estado coherente. Esto significa que el estado del objeto (los valores de sus campos) Deben representar a un estado usable. Si no se ha inicializado el campo, Los valores por defecto deben ser "" para los campos string y 0 para los campos integer. Aunque los valores sean aceptables para un Hospital, y se podría dejarlos sin inicializar. Debido a que los compiladores pueden cambiar los valores por defecto, se deben evitar dichos problemas inicializando los campos. El código de cliente (el código que utiliza un objeto de la clase Hospital) es capaz de leer y escribir en cualquier campo declarado con la palabra clave pública (Public). Proporcionar acceso directo a los datos de la clase es una violación del principio de orientación a objetos. La ocultación de información estipula que el cliente no debe tener conocimiento de la estructura subyacente de los datos de un objeto. En la siguiente sección, aprenderemos cómo permitir que el código de cliente escriba y lea campos de la clase CHospital sin revelar detalles sobre la implementación interna de la clase. Añadir la propiedad Salas Una propiedad es una construcción de programación que permite al código obtener y establecer un valor. Por lo general, los códigos constructores de la propiedad Get y Set deben ser campos privados de la clase. En el código de cliente, un campo público y una propiedad se usan de la misma forma, por ejemplo. HospitalNorte.Salas y HospitalNorte.Direccion Añadir el siguiente código a la clase CHospital después de las declaraciones de Salas, Telefono y Direccion. Private m_num_salas As integer Este código crea un campo privado en la clase CHospital. El código de cliente no tiene el acceso a esta propiedad. Sugerencia: Los campos privados de una clase se declaran mediante el prefijo m_ para identificarlos como datos de los miembros. Los nombres particulares de campo no se capitalizan. Añadir el siguiente código a la clase CHospital después de la declaración m_direccion. Public Property NumSalas() As Integer Get Return m_num_salas End Get Set(ByVal value As Integer) m_num_salas = value End Set End Property Estos bloques de sintaxis definen las propiedades de la clase. La propiedad aparece en el título Y con IntelliSense sale una lista desplegable mostrando sus propiedades. El bloque de propiedades permite controlar el acceso a la propiedad. Se puede agregar código de validación para el bloque Set para garantizar que sólo recoge valores razonables asignados al campo m_salas subyacente. Nota: Hay que tener en cuenta una diferencia importante entre los campos y las propiedades. En un campo se reserva un lugar en la memoria, y contienen los datos reales de la clase. Las propiedades proveen el acceso a los datos pero no son ellas mismas los datos. En estos ejercicios, se usa la palabra Set en el sentido de establecer el cambio de una propiedad. Y se usa la palabra Get en el sentido de recuperar el valor de una propiedad. Los bloques Get y Set de una propiedad pueden ser llamados getters y setters, o accesores. El bloque de propiedad es más flexible de lo que se ha visto aquí. Las propiedades pueden ser públicas o privadas, de lectura/escritura, sólo lectura o sólo escritura. En Visual Basic, las declaraciones de la propiedad pueden incluso tomar un parámetro. Un poco sobre las propiedades Se puede usar la palabra propiedades como significado de la información sobre un objeto (por ejemplo el color de un coche es una propiedad del coche) o también utilizarla en el sentido de la construcción sintáctica de un programa (propiedad color de la clase CCoche) El significado de la palabra se determinará por el contexto. Las propiedades deben validar los datos de la clase y ocultar su implementación. Añadir una propiedad a una clase para controlar el acceso a los datos de la clase requiere un esfuerzo muy bajo y se obtiene con ello un beneficio al poder agregar fácilmente una validación o cambiar incluso la implementación si fuera necesario sin afectar por ello al resto del programa. En cualquier caso no se deben usar campos públicos en la clase a no ser que se tenga una fuerte razón para ello. Añadir el método AltaMedicoHos Antes de nada hay que añadir el Objeto Microsoft Remote Data Object 2.0 al proyecto para poder acceder a la base de datos. Para ello procedemos del siguiente modo:
Y elegimos Microsoft Remote Data Object 2.0
Creamos un módulo general para colocar las variables globales. Module General Public glbBaseDatos As RDO.rdoConnection End Module Y esta es la definición que quedaría dentro de la clase CHospital Public Function AltaMedicoHos(ByVal Nom_Medico As CPersona, ByVal Hospital As CHospital) As Boolean Dim Reg As RDO.rdoResultset Dim strSQL As String Reg = Nothing On Error GoTo Errores_AltaMedicoHos strSQL = "INSERT INTO dbo.tbMedHos (strId_MED,strID_HOS) VALUES (" & Nom_Medico.Medico & "," & Hospital.Codigo & ")" glbBaseDatos.Execute(strSQL) Reg.Close() Return True Errores_AltaMedicoHos: Return False End Function Se muestra a continuación la definición completa de la clase para este proyecto: Public Class CHospital Private m_codigo As String Private m_num_salas As integer = 0 Private m_telefono As String = "" Private m_direccion As String = "" Public Property Codigo() As Integer Get Return m_codigo End Get Set(ByVal value As Integer) m_codigo = value End Set End Property Public Property NumSalas() As Integer Get Return m_num_salas End Get Set(ByVal value As Integer) m_num_salas = value End Set End Property Public Property Telefono() As String Get Return m_telefono End Get Set(ByVal value As String) m_telefono = value End Set End Property Public Property Direccion() As String Get Return m_direccion End Get Set(ByVal value As String) m_direccion = value End Set End Property Public Function AltaMedicoHos(ByVal Nom_Medico As CPersona, ByVal Hospital As CHospital) As Boolean Dim Reg As RDO.rdoResultset Dim strSQL As String Reg = Nothing On Error GoTo Errores_AltaMedicoHos strSQL = "INSERT INTO dbo.tbMedHos (strId_MED,strID_HOS) VALUES (" & Nom_Medico.Medico & "," & Hospital.Codigo & ")" glbBaseDatos.Execute(strSQL) Reg.Close() Return True Errores_AltaMedicoHos: Return False End Function End Class Campos, propiedades, métodos y constructores deben aparecer en una definición de una clase Para una buena organización conviene seguir el siguiente orden: Declaraciones de campos Constructores Propiedades Métodos Resumen Añadir una clase al proyecto. En el menú de proyecto clicar Add Class o escribir Class NombreClase End Class Añadir un campo a la clase, declarar una variable en el bloque de la clase. Class NombreClase Dim Campo as string End Class Añadir una propiedad a la clase, escribir el método dentro del bloque de la clase Public Property Titulo() As String Get ‘ Aquí retorna un valor del campo End Get Set(ByVal Value As String) ‘ Aqui pone un valor al campo End Set End Property Añadir un método a la clase, escribir el método dentro del bloque de la clase Class NombreClase Private Sub Metodo() End sub End Class

Programacion Orientada a Objetos (POO) III

Principios de la programación orientada a objetos (III) Cómo identificar las Clases y Objetos En el mundo real es sencillo identificar los objetos, sus atributos y sus funciones, pero a la hora de hacer un programa informático esta identificación no resulta tan evidente. Los objetos desde la realidad se manifiestan como: Entidades Externas. Pueden ser cosas o personas externos al sistema pero que producen o consumen información del sistema. Cosas. Objetos físicos del sistema, informes, facturas, maquinas, etc. Ocurrencias o sucesos. Cuando se produce un cambio en el tiempo, sacar dinero de una cuenta, una máquina llega al final de carrera, etc. Papeles o roles. Los desempeñados por personas que interactúan en el sistema Unidades organizacionales. Si son relevantes en un sistema, división, equipo, etc. Lugares. Establecidos en el contexto del sistema. Planta, Nº de aparcamiento, Plaza, Almacén, etc. Estructuras. Una clase de objetos, maquinas, sensores, etc. Así por ejemplo para un programa que juegue al ajedrez podemos identificar: Clase/ Objeto Potencial Jugador -> entidad externa o rol Pieza ->cosa Tablero -> cosa Posición -> atributo de la pieza Captura -> ocurrencia Movimiento -> ocurrencia Color -> atributo de la pieza Para definir las clases y los objetos conviene analizar sintácticamente el enunciado o especificación del software a desarrollar detectando los posibles objetos (nombres) y los posibles métodos (verbos). Se han definido seis características para considerar si se incluye un objeto en un modelo de análisis: Servicios Necesarios. Debe ser capaz de cambiar el valor de sus atributos a través de un conjunto de operaciones identificables. Información retenida. La información acerca del objeto debe ser recordada para que el sistema funcione. Atributos Múltiples. Un objeto debe tener atributos múltiples, si sólo tiene uno se puede considerar durante el análisis pero seguramente se pueda incluir dicho atributo dentro de otro objeto Operaciones Comunes. Las operaciones tienen que ser aplicables a todas las ocurrencias del objeto. Atributos Comunes. Los atributos tienen que ser aplicables a todas las ocurrencias del objeto. Requisitos esenciales. Las entidades externas que intervienen en el problema consumiendo o produciendo información esencial para el sistema también deben ser incluidas como objetos. Para incluir un objeto en nuestro modelo, debe satisfacer la mayoría de los puntos mostrados anteriormente. Una vez elegido el objeto, sus atributos se buscan con la premisa de que definan completamente los objetos que los hacen únicos. Si retomamos el ejemplo del ajedrez podemos ver si cumplen los requisitos. Clase/ Objeto Potencial Jugador -> entidad externa o rol Rechazado: no cumple muchas características. Pieza ->cosa Aceptado: Cumple todas Tablero -> cosa Rechazado: solo contiene la posición que pasa a atributo de la pieza Posición -> atributo de la pieza. Pasa a atributo de la pieza Captura -> ocurrencia. Pasa a método de la pieza Movimiento -> ocurrencia. Pasa a método de la pieza Color -> atributo de la pieza. Pasa a atributo de la pieza Para encontrar las operaciones (métodos) hay que prestar atención a los verbos de la definición del sistema. Así en la definición del juego de ajedrez el verbo mover es importante y define un método. También existe el verbo capturar, por lo que habrá que tenerlo en cuenta a la hora de diseñar la clase. Finalmente tendremos sólo una clase principal llamada Pieza que tendrá como propiedades el color de la pieza y su posición sobre el tablero, también será necesario añadir otra propiedad que no viene en la lista que nos diga el tipo de pieza de que se trata. Tendrá un método mover y otro capturar que puede fusionarse como caso especial del método mover. También es conveniente heredar una clase para cada tipo de pieza. De este modo tendremos la clase padre Pieza con las clases hijas Peón, Torre, Caballo, Alfil, Rey y Reina, todas heredan todos los atributos como Color, Posición, etc. y cada una de ellas implementa un método diferente llamado Mover que incluye el caso especial Capturar. Dicho caso especial obliga a introducir otro atributo en la clase pieza que nos indique si la pieza está en juego o no. El sistema para un lenguaje concreto (Visual Basic.NET) se representaría así en UML:

Programacion Orientada a Objetos (POO) II

/*Este texto no es de mi autoría. Viene del autor del blog analisisyprogramacionoop*/ 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 color. El 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