I.- FUNDAMENTOS DE PROGRAMACIÓN ORIENTADA A OBJETOS

Anuncio
Fundamentos de Programación Orientada a Objetos
I.- FUNDAMENTOS DE PROGRAMACIÓN ORIENTADA A OBJETOS
1.1 Evolución de la programación
1.2 Conceptos fundamentales de la Programación Orientada a Objetos
1.2.1 Los lenguajes orientados a objetos
1.3 Relaciones entre clases y objetos
1.4 El papel de clases y objetos en el análisis y el diseño
Página 1
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
I.- FUNDAMENTOS DE PROGRAMACIÓN ORIENTADA A OBJETOS
1.1 Evolución de la programación
1.2 Conceptos fundamentales de la Programación Orientada a Objetos
1.2.1 Los lenguajes orientados a objetos
1.3 Relaciones entre clases y objetos
1.4 El papel de clases y objetos en el análisis y el diseño
1.1 Evolución de la programación
•
La evolución de la programación puede sintetizarse en tres modelos o paradigmas:
El significado de paradigma (paradigma en latín; paradeigma en griego) en su origen significaba un ejemplo ilustrativo; en particular, enunciado modelo que mostraba
todas las inflexiones de una palabra. Un paradigma es una forma establecida de pensar acerca de cómo hacer algo. En el libro The Structure of Scientific Revolutions, el
historiador Thomas Kuhn describía un paradigma como un conjunto de teorías, estándares y métodos que juntos representan un medio de organización del conocimiento: es decir, un medio de visualizar el mundo.
‰
‰
‰
La programación mediante procedimientos (procedural),
La programación estructurada y
La programación orientada a objetos
PROGRAMACION MEDIANTE PROCEDIMIENTOS [PROCEDURAL]
Programación y abstracción
•
•
•
•
•
•
•
•
•
•
La abstracción es el proceso de extraer las propiedades relevantes de un objeto al tiempo que se ignoran los detalles
no esenciales. Las propiedades extraídas definen una vista del objeto. En esencia, la abstracción supone la capacidad de encapsular y aislar, la información del diseño, de la ejecución.
Definir una abstracción significa describir una entidad del mundo real, no importa lo compleja que pueda ser y, a
continuación, utilizar esta descripción en un programa.
La abstracción es fundamental para gestionar la complejidad del diseño y escritura del software. La abstracción es la
clave para diseñar buen software. La abstracción es uno de los medios más importantes, mediante el cual nos enfrentamos con la complejidad inherente al software.
Una abstracción se centra en la vista externa de un objeto, de modo que sirva para separar el comportamiento esencial
de un objeto de su implementación
Como describe Wulft: «Los humanos hemos desarrollado una técnica excepcionalmente potente para tratar la complejidad: abstraemos de ella. Incapaces de dominar en su totalidad los objetos complejos, se ignora los detalles no esenciales, tratando en su lugar con el modelo ideal del objeto y centrándonos en el estudio de sus aspectos esenciales.»
El proceso de abstracción fue evolucionando desde la aparición de los primeros lenguajes de programación.
La abstracción es esencial para el funcionamiento de una mente humana normal y es una herramienta muy potente
para tratar la complejidad. El método más idóneo para controlar la complejidad es aumentar los niveles de abstracción.
Las personas normalmente comprenden el mundo construyendo modelos mentales de partes del mismo; tratan de
comprender cosas con las que pueden interactuar. Un modelo mental es una vista simplificada de cómo funciona, de
modo que se pueda interactuar con ella.
En esencia, este proceso de construcción de modelos es lo mismo que el diseño de software, aunque el desarrollo de
software es único: el diseño de software produce el modelo que puede ser manipulado por una computadora.
Sin embargo, los modelos mentales deben ser más sencillos que el sistema al cual imitan, o en caso contrario serán
inútiles. Por ejemplo, consideremos un mapa como un modelo de su territorio. A fin de ser útil, el mapa debe ser más
sencillo que el territorio que modela. Un mapa nos ayuda, ya que abstrae sólo aquellas características del territorio que
deseamos modelar. Un mapa de carreteras modela cómo conducir mejor de una posición a otra. Un mapa topográfico
modela el contorno de un territorio, quizá para planear un sistema de largos paseos o caminatas.
Página 2
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
•
•
•
•
•
•
•
•
•
•
•
•
•
•
De igual forma que un mapa debe ser más pequeño significativamente que su territorio e incluye sólo información
seleccionada cuidadosamente, así los modelos mentales abstraen esas características de un sistema requerido para
nuestra comprensión, mientras ignoran características irrelevantes. Este proceso de abstracción es psicológicamente
necesario y natural: la abstracción es crucial para comprender este complejo mundo.
Un conjunto se puede definir por abstracción como una colección no ordenada de elementos en el que no existen
duplicados. Utilizando esta definición, se puede especificar si sus elementos se almacenan en un arreglo, una lista enlazada o cualquier otra estructura de datos.
Un vendedor de coches podría ver un coche desde el punto de vista de sus características de venta. Propiedades
relevantes serían el precio, el color, el equipo opcional y la duración de la garantía. Por otro lado, un mecánico vería el
coche desde el punto de vista de los sistemas que necesitan mantenimiento. Para él, propiedades relevantes serían el
motor, sistema electrónico de encendido, tipo de aceite, el tamaño del filtro de aceite y el número y tipo de bujías. Las
propiedades relevantes de un objeto vienen definidas por la forma en que se usa o manipula el objeto.
Claramente las propiedades de un coche, importantes para un vendedor, son distintas de las de un mecánico. Enfocándose sobre las propiedades relevantes e ignorando los detalles irrelevantes, se puede reducir la complejidad de
manejo de un objeto.
Consideremos la tarea de encontrar un archivo en un disco y leer su contenido. Si tuviésemos que manejar todos los
detalles de bajo nivel para saber cómo encontrar un archivo concreto en el disco y cómo leer sus contenidos, sería una
tarea bastante difícil. Deberíamos comprender cómo se almacenan los datos en los discos y todos los mandatos de bajo nivel que controlan las operaciones del manejador de disco. Afortunadamente, existe un sistema de archivos que
proporciona una visión abstracta de la información en un disco, de forma que se pueden ignorar los detalles de bajo nivel. Se puede acceder al archivo sin más que proporcionar su nombre. El sistema de archivos maneja los detalles de
bajo nivel para leer los datos en el disco y devolverlos al programa.
El arte de la programación es el método por el que se describirá a una computadora (mediante un lenguaje de programación) un fenómeno, una acción, un comportamiento o una idea. En general, un programa no es más que una
descripción abstracta de un procedimiento o fenómeno que existe o sucede en el mundo real. Frecuentemente, un
programa imita un comportamiento o acción humana; otras veces simula (es decir, reproduce) un fenómeno físico.
Sin embargo, la relación entre abstracción y lenguaje de programación es doble: por un lado se utiliza el lenguaje de
programación para escribir un programa que es una abstracción del mundo real; por otro lado se utiliza el lenguaje de
programación para describir de un modo abstracto el comportamiento físico de la computadora que se está utilizando
(por ejemplo, utilizando números decimales en lugar de números binarios, variables en lugar de celdas de memoria direccionadas explícitamente, etc.).
En los primeros días de la informática, los programadores enviaban instrucciones binarias a una computadora, manipulando directamente interrupciones en sus paneles frontales.
En la década de los cincuenta, los únicos mecanismos de abstracción eran el lenguaje de máquina y el lenguaje ensamblador. El lenguaje ensamblador ofrecía la posibilidad de utilizar mnemónicos, que eran abstracciones diseñadas
para evitar que los programadores tuvieran que recordar las secuencias de bits que componen las instrucciones de un
programa. Ofrece también la posibilidad de utilizar nombres simbólicos para representar celdas de memoria.
El siguiente nivel de abstracción se consigue agrupando instrucciones primitivas para formar macroinstrucciones. Un
conjunto de instrucciones realizadas por un usuario se pueden invocar por una macroinstrucción; una macroinstrucción
instruye a la máquina para que realice muchas cosas.
Tras los lenguajes de programación ensambladores aparecieron los lenguajes de programación de alto nivel, que
supusieron un nuevo nivel de abstracción.
Los lenguajes de programación de alto nivel permitieron a los programadores distanciarse de las características arquitectónicas específicas de una máquina dada. Cada instrucción en un lenguaje de alto nivel puede invocar varias instrucciones máquina, dependiendo de la máquina específica donde se compila el programa. Esta abstracción permitía a
los programadores escribir software para propósito genérico, sin preocuparse sobre qué máquina ejecutaría el programa.
Secuencias de sentencias de lenguajes de alto nivel se pueden agrupar en procedimientos y se invocan por una sentencia.
El mundo en que vivimos se halla plagado de objetos: aviones, trenes, automóviles, teléfonos, libros, computadoras,
etcétera. Sin embargo, en esa época las técnicas de programación no reflejaban esto. Lo procedural [procedimientos]
fue el paradigma principal de la programación, el cual define un programa como un algoritmo escrito en algún lenguaje
de programación. Las razones de este énfasis son principalmente históricas.
Página 3
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
•
•
•
•
•
•
•
Desde la época de su desarrollo, durante los años cuarenta, las computadoras fueron utilizadas por los matemáticos
con propósitos militares: el cálculo de trayectorias de bombas y la decodificación de transmisiones hecha por el enemigo o por diplomáticos son algunos ejemplos de estos propósitos. Después de la segunda guerra mundial, las computadoras todavía eran utilizadas, principalmente, por los matemáticos para resolver problemas con su disciplina. Este panorama se reflejó en el primer lenguaje de programación de alto nivel comercialmente disponible, el cual se introdujo
en 1957. Este lenguaje fue FORTRAN, cuyas siglas son un acrónimo para FORmula TRANslation (traducción de
fórmulas).
Un reflejo adicional de este uso predominante es el hecho de que en los años sesenta casi todos los cursos de computación se impartían en los departamentos de ingeniería o matemáticas. El término de ciencia de la computación todavía
no era de uso común y los departamentos de ciencia de la computación se encontraban en desarrollo.
Esta situación sufrió un cambio drástico principalmente por dos razones. Una de las desventajas con los programas
orientados a procedimientos es el fracaso de los lenguajes tradicionales basado en procedimientos en proporcionar
medios adecuados para limitar el costo del software, lo cual incluye todos los costos asociados al desarrollo inicial del
programa y su mantenimiento subsecuente.
La inversión en sofware contribuye en gran medida a los costos totales del proyecto porque están relacionados directamente con la productividad humana (son sensibles al esfuerzo laboral), mientras que el costo asociado al hardware
se relaciona con la tecnología de fabricación. Por ejemplo, los microchips que se adquirían por más de 500 dólares
hace diez años, ahora se pueden comprar por menos de un dólar.
Es mucho más fácil, aumentar drásticamente la productividad de fabricación en un 1000% con la consecuente reducción en costo del hardware, que los programadores dupliquen la cantidad o la calidad del código que producen. Si bien
los costos del hardware se desplomaron, la productividad de software y los costos relacionados con su desarrollo permanecieron relativamente constantes.
Otra de las desventajas de la programación basada en procedimientos fue la aparición de pantallas gráficas y el interes
subsecuente en las aplicaciones utilizando ventanas. El acceso a una interfaz gráfica de usuarios (GUI) donde un
usuario puede moverse con facilidad alrededor de una sola ventana es un desafío cuando se intenta lograrlo con un
código procedural. La programación múltiple y las posibles ventanas que se traslapan en una misma pantalla gráfica
simplemente aumenta la enorme complejidad cuando se utiliza código procedural.
Las razones anteriores movitaron la búsqueda de nuevas soluciones o mejoras a la programación mediante procedimientos, lo que condujo a la programación estructurada.
PROGRAMACION ESTRUCTURADA
•
Durante la década de los sesenta, muchos de los grandes esfuerzos para el desarrollo de software encontraron severas dificultades:
‰
‰
‰
•
Los tiempos del desarrollo de software generalmente se retrasaban
Los costos rebasaban en gran medida a los presupuestos y
Los productos terminados no eran confiables
La gente comenzó a darse cuenta de que el desarrollo de software era una actividad mucho más compleja de lo que
habían imaginado. Las actividades de investigación en la década de los sesenta dieron como resultado la evolución de
la programación mediante procedimientos a la programación estructurada, un método disciplinado para escribir programas que son:
‰
‰
‰
Más claros
Fáciles de probar y corregir y
Más fáciles de modificar que los no estructurados
Estas mejoras de la programación mediante procedimientos condujeron a nuevos conceptos como son: Estructuras de control, funciones
y módulos.
Estructuras de control
•
Tal como los arquitectos diseñan edificios empleando la sabiduría colectiva de su profesión, así deberían los programadores diseñar sus programas. Nuestro campo es más joven que la arquitectura y nuestra sabiduría colectiva es
considerablemente menor.
Página 4
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
•
Aprendimos que la programación estructurada produce programas que son más fáciles de entender, probar, corregir,
modificar, e incluso comprobar en el sentido matemático, que los programas que no están estructurados.
•
La figura 1.1 utiliza diagramas de actividad (o de flujo) para resumir las estructuras de control.
•
Los estados inicial y final indican la entrada y salida sencillas de cada estructura de control.
•
•
Conectar de manera arbitraria símbolos individuales en un diagrama de actividad puede provocar que los programas
no estén estructurados.
Por lo tanto, la profesión de computación eligió un conjunto limitado de estructuras de control que se pueden combinar
solamente de dos sencillas maneras para construir programas estructurados.
Figura 1.1. Estructuras de secuencia de entrada sencilla/salida sencilla, selección y repetición de C++.
•
•
•
•
Por simplicidad, solamente se utilizan estructuras de entrada sencilla /salida sencilla; sólo existe una forma de entrar y
una forma de salir de cada estructura de control.
Conectar estructuras de control en secuencia para formar programas estructurados es sencillo, el estado final de una
estructura de control se conecta con el estado inicial de la siguiente estructura de control, esto es, las estructuras de
control se colocan una sobre la otra en el programa. A esto le llamamos apilar estructuras de control.
Las reglas para formar programas estructurados permiten, además, anidar estructuras de control.
La figura 1.2 muestra las reglas para formar programas estructurados. Además, las reglas suponen que comenzamos
con el diagrama de actividad más sencillo (figura 1.3), el cual consiste solamente en un estado inicial, un estado de acción, un estado final y flechas de transición.
Página 5
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
Reglas para formar programas estructurados
1.
2.
3.
4.
Comience con el diagrama de actividad más sencillo (figura 1.3).
Cualquier estado de acción se puede reemplazar por dos estados de acción en secuencia.
Cualquier estado de acción se puede representar mediante cualquier estructura de control (secuencia, if, if/else,
switch, while, do/while o for).
Las reglas 2 y 3 se pueden aplicar con la frecuencia que usted desee, en cualquier orden.
Figura 1.2. Reglas para formar programas estructurados.
Figura 1.3. Diagrama de actividad más sencillo.
•
•
•
•
Aplicando las reglas de la figura 1.2 se produce un diagrama de actividad con la apariencia de una cuidadosa construcción con bloques.
Por ejemplo, al aplicar de manera repetida la regla 2 al diagrama de actividad más sencillo, provoca un diagrama de
actividad que contiene muchos estados de acción en secuencia (figura 1.4).
La regla 2 genera una pila de estructuras de control, de manera que llamaremos a la regla 2 la regla del apilado.
[Nota: Las líneas verticales punteadas de la figura 1.4 no son parte del UML. Las utilizamos para separar los cuatro
diagramas de actividad que muestran la aplicación de la regla 2 de la figura 1.2.]
Figura 1.4. Aplicación repetida de la regla 2 de la figura 1.2 al diagrama de actividad más sencillo.
•
•
•
•
•
La regla 3 se llama regla de anidamiento.
Al aplicar de manera repetida la regla 3 al diagrama de actividad más sencillo, provoca un diagrama de actividad con
estructuras de control anidadas más pulcras.
Por ejemplo, en la figura 1.5 el estado de acción del diagrama de actividad más sencillo se reemplaza con una estructura de selección doble (if/else).
Entonces, la regla 3 se aplica de nuevo a los estados de acción en la estructura de selección doble, y reemplaza cada
uno de estos estados de acción con una estructura de selección doble.
Los símbolos punteados de estados de acción alrededor de cada una de las estructuras de selección doble representan el estado de acción que se reemplazó en el diagrama de actividad más simple original.
Página 6
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
•
[Nota: Las flechas punteadas y los símbolos de estados de acción punteados que aparecen en la figura 1.5 no son
parte del UML. Aquí los utilizamos como ayudas pedagógicas para mostrar que cualquier estado de acción se puede
representar mediante una estructura de control].
Figura 1.5. Aplicación repetida de la regla 3 de la figura 1.2 al diagrama de actividad más sencillo
•
•
•
•
•
La regla 4 genera estructuras anidadas más grandes, más involucradas y más profundas.
Los diagramas que surgen de la aplicación de las reglas de la figura 1.2 constituyen un conjunto de todos los diagramas de actividad posibles y, por lo tanto, el conjunto de todos los posibles programas estructurados.
La belleza del método estructurado es que utilizamos sólo siete estructuras de control de entrada sencilla/salida sencilla y las ensamblamos solamente de dos maneras posibles.
Si se siguen las reglas de la figura 1.2, no se puede escribir un diagrama de actividad con sintaxis incorrecta (tal como
el de la figura 1.6).
Si no está seguro de si un diagrama en particular es correcto, aplique las reglas de la figura 1.2 a la inversa, para
reducir el diagrama al diagrama de actividad más sencillo. Si el diagrama se reduce al diagrama de actividad más sencillo, el original está estructurado, de lo contrario, no lo está.
Página 7
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
Figura 1.6. Diagrama de actividad con sintaxis no permitida.
•
Resumiendo
Los resultados de Bohm y Jacopini indican que sólo se necesitan tres formas de estructuras de control:
‰
‰
‰
•
•
La estructura de secuencia es trivial. Simplemente liste las instrucciones a ejecutar, en el orden en el que se deben
ejecutar:
La selección se implementa en una de estas tres maneras:
‰
‰
‰
•
•
•
La repetición se implementa en una de estas tres formas:
•
•
•
estructura while.
estructura do/while.
estructura for.
Es sencillo probar que la estructura while es suficiente para proporcionar cualquier forma de repetición. Todo lo que se
puede hacer con una estructura do/while y con la estructura for, se puede hacer con la estructura while (aunque quizá
no de manera sencilla).
La combinación de estos resultados muestra que cualquier forma de control necesaria en un programa en C++ se
puede expresar en términos de las siguientes estructuras de control:
‰
‰
‰
•
Estructura if (selección simple).
Estructura if/else (selección doble).
Estructura switch (selección múltiple).
De hecho, es bastante sencillo probar que la estructura if sencilla es suficiente para proporcionar cualquier forma de
selección, todo lo que se puede hacer con la estructura if/else y la estructura switch se puede implementar mediante la
combinación de estructuras if (aunque quizá no sea tan claro y eficiente).
‰
‰
‰
•
Secuencia.
Selección.
Repetición.
secuencia.
estructura if (selección).
estructura while (repetición).
Estas estructuras de control se pueden combinar solamente de dos maneras, apiladas o anidadas. En realidad, la
programación estructurada promueve la simplicidad. La programación estructurada alienta el uso de abstracciones de
control, tales como ciclos, sentencias if-then, que se han incorporado en lenguajes de alto nivel. Estas sentencias de
control permitieron a los programadores abstraer las condiciones comunes para cambiar la secuencia de ejecución.
Nuestro objetivo es explicar cómo crear programas a partir de estructuras de control que contienen estados de acción y
decisión.
Veremos a continuación otra unidad de programación estructurada llamada función. Aprenderemos a crear programas
grandes mediante la combinación de funciones que, a su vez, están compuestas por estructuras de control.
También explicaremos cómo es que las funciones promueven la reutilización del software.
Página 8
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
Funciones
•
•
•
•
•
Las funciones o procedimientos fueron uno de los primeros mecanismos de abstracción que se utilizaron ampliamente en los lenguajes de programación.
Las funciones permiten realizar tareas que se ejecutaban repetidamente, o son ejecutadas con ligeras variaciones,
que se reunen en una entidad y se reutilizan, en lugar de duplicar el código varias veces.
Por otra parte, el concepto de función proporcionó la primera posibilidad de ocultamiento de la información. Un programador puede escribir un procedimiento o conjunto de procedimientos que utilizan otros programadores. Estos programadores no necesitaban conocer con exactitud los detalles de la implementación; sólo necesitaban el interfaz necesario.
Sin embargo, las funciones no resuelven todos los problemas. En particular, no es un mecanismo efectivo para ocultar
la información, tampoco resuelve el problema que se produce al trabajar múltiples programadores con nombres de
procedimientos idénticos.
Para resolver este problema se ha desarrollado un mecanismo de estructuración diferente.
Módulos
•
•
•
•
•
•
•
•
La modularidad se refiere al proceso de dividir un objeto en piezas más pequeñas, o módulos, para que algún objetivo
sea más fácil de conseguir. Por ejemplo, se podría dividir un sistema complejo en componentes, de forma que cada
componente pueda ser probado de forma individual. Cuando se monta un automóvil, sus distintos componentes, tales
como el motor, la transmisión y el radio, han sido ya probados individualmente. La modularidad reduce el tiempo para
probar el coche y la probabilidad de que un coche sea montado con un defecto.
La mayoría de los sistemas complejos son modulares. Están construidos combinando componentes o paquetes, de
funcionamiento más sencillo. Una adecuada modularización de un sistema complejo también ayuda a manejar su
complejidad. Dividir las cosas en piezas más pequeñas y más sencillas de entender hace que un sistema grande sea
más sencillo de comprender.
Como se verá la modularidad es la propiedad de un sistema que permite su descomposición en un conjunto de módulos cohesivos y débilmente acoplados.
En computación la modularidad es la propiedad que permite subdividir una aplicación en partes más pequeñas (llamadas módulos), cada una de ellas debe ser tan independiente como sea posible de la aplicación en sí y de las restantes partes.
La modularización, como indica Liskov, consiste en dividir un programa en módulos que se puedan compilar por
separado, pero que tienen conexiones con otros módulos.
Un módulo es una técnica que proporciona la posibilidad de dividir sus datos y procedimientos en una parte privada sólo accesible dentro del módulo- y parte pública -accesible fuera del módulo-. Se pueden definir tipos, datos (variables
y procedimientos) en cualquiera de las dos partes.
El criterio a seguir en la construcción de un módulo es que si no se necesita algún tipo de información, no se debe
tener acceso a ella. Este criterio es el ocultamiento de la información.
Una clasificación de objetos basada en alguna relación entre ellos es una jerarquía. Las jerarquías también ayudan a
comprender sistemas y organizaciones complejas. La figura 1.7 incluye un diagrama de organización de una compañía típica. El diagrama muestra la jerarquía de empleados basándose en la relación de quién informa a quién. La jerarquía de la compañía ayuda a los empleados a comprender la estructura de su compañía y su relación dentro de ella.
Página 9
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
Director
Director de
ventas
Tesorero
Gerente
ventas zona
Gerente de
ventas zona
Gerente
ventas zona
Gerente
ventas zona
Director de
investigación
Director de
operaciones
Jefe científico
Gerente de
patentes
Desarrollo de
lenguajes de
programación
Investigación de
patentes
Desarrollo
sistema
Aplicación de
patentes
Desarrollo de
aplicaciones
Figura 1.7. Diagrama de la organización de una compañía
•
•
•
•
•
Los científicos han usado esta técnica desde hace mucho tiempo para identificar y clasificar especies del reino animal
y vegetal. Un orden jerárquico basado en las relaciones de la naturaleza se denomina taxonomía. Tal jerarquía hace
que las abstracciones sean más fáciles de entender porque expone la relación entre características y comportamientos
comunes.
Un concepto importante introducido con la programación estructurada, ya comentado anteriormente, es el de abstracción, que se puede definir como la capacidad para examinar algo sin preocuparse de sus datos internos.
Una forma de ordenar abstracciones similares, en sistemas complejos compuestos de abstracciones, es ir del concepto más general al menos general.
La técnica top-down, descendente, o refinamiento sucesivo comienza descomponiendo el programa en piezas manejables más pequeñas, conocidas como funciones (subrutinas, subprogramas o procedimientos), que realizan tareas
menos complejas.
En un programa estructurado es suficiente conocer que un procedimiento dado realiza una tarea específica. El cómo
se realiza esta tarea no es importante, sino conocer cómo se utiliza correctamente la función y lo que hace.
Funciones
Función1
Función11
Función2
Función21
Función22
Función3
Función31
Función221
Función311
Función4
Función41
Función42
Función411
Figura 1.8. Programa estructurado.
•
Un programa estructurado se construye rompiendo el programa en funciones. Esta división permite escribir código más
claro y mantener el control sobre cada función.
Página 10
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
•
•
•
•
•
•
•
•
•
Los módulos resuelven algunos problemas, pero no todos los problemas del desarrollo de software.
Por ejemplo, los módulos permitirán a nuestros programadores ocultar los detalles de la implementación de su pila,
pero ¿qué sucede si otros usuarios desean tener dos o más pilas?
Supongamos que un programador ha desarrollado un tipo de dato complejo o (representación de un número complejo) y ha definido las operaciones aritméticas sobre números complejos -suma, resta, multiplicación y división-; asimismo ha definido rutinas para convertir números convencionales a complejos. Se presenta un problema: sólo puede manipular un número complejo. El sistema de números complejos no será útil con esta restricción, pero es la situación en
que se encuentra el programador con módulos simples.
Los módulos proporcionan un método efectivo de ocultamiento de la información, pero no permiten realizar instanciación, que es la capacidad de hacer múltiples copias de las zonas de datos.
A medida que la complejidad de un programa crece, también crece su independencia de los tipos de datos fundamentales que procesa.
En un programa estructurado, las estructuras de datos de un programa son tan importantes como las operaciones
realizadas sobre ellas. Esto se hace más evidente a medida que crece un programa en tamaño.
Los tipos de datos se procesan en muchas funciones dentro de un programa estructurado, y cuando se producen
cambios en esos tipos de datos, las modificaciones se deben hacer en cada sentencia que actúa sobre esos tipos de
datos dentro del programa.
Esta tarea puede ser frustrante y consumir un tiempo considerable en programas con millones de líneas de código y
miles de funciones.
En un programa estructurado, los datos locales se ocultan dentro de funciones y los datos compartidos se pasan como
argumentos (Fig. 1.9).
Variables globales
Accesibles, por cualquier función
Variables locales
Variables locales
Función A
Función B
Accesible sólo por función A
Accesible sólo por función B
Figura 1.9. Variables globales y locales.
•
•
Dado que muchas funciones acceden a los mismos datos, el medio en que se almacenan los datos se hace más crítico.
La disposición de los datos no se puede cambiar sin modificar todas las funciones que accedan a ellos. Si, por ejemplo, se añaden nuevos datos, se necesitará modificar todas las funciones que accedan a los datos, de modo que ellos
puedan también acceder a esos elementos.
Página 11
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
Datos
globales
Datos
globales
Función1
Función2
Datos
globales
Función3
Función4
Figura 1.10. Descomposición de un programa en módulos (funciones)
•
•
•
Resumiendo
La programación estructurada se emplea desde el principio de la década de los setenta y es uno de los métodos más
utilizados en el campo de la programación.
Uno de los resultados más tangibles de esta investigación fue el desarrollo del lenguaje de programación estructurado
Pascal por Niklaus Wirth, en 1971. Pascal, cuyo nombre se debe al aniversario de los setecientos años del nacimiento
del filósofo y matemático Blas Pascal, fue diseñado para la enseñanza de la programación estructurada en ambientes
académicos; convirtiéndose en el lenguaje de programación favorito en varias universidades.
Desafortunadamente, el lenguaje carecía de muchas de las características necesarias para poder utilizarse en aplicaciones comerciales, industriales y gubernamentales, de manera que no ha sido muy aceptado fuera de las universidades.
Desventajas de la programación estructurada
•
•
•
•
•
•
•
•
•
•
Los programas basados en funciones son difíciles de diseñar. El problema es que sus componentes principales funciones y estructuras de datos- no modelan bien el mundo real.
Por ejemplo, supongamos que se está escribiendo un programa para crear los elementos de un interfaz gráfico de
usuario: menús, ventanas, cuadros de diálogo, etc. ¿Qué funciones se necesitarán? ¿Qué estructuras de datos?
La solución sería más aproximada si hubiera una correspondencia lo más estrecha posible entre los menús y ventanas
y sus correspondientes elementos de programa.
Cuando diferentes programadores trabajan en equipo para diseñar una aplicación, a cada programador se le asigna la
construcción de un conjunto específico de funciones y tipos de datos. Dado que los diferentes programadores manipulan funciones independientes que relacionan a tipos de datos compartidos mutuamente, los cambios que un programador hace a los datos se deben reflejar en el trabajo del resto del equipo.
Aunque los programas estructurados son más fáciles de diseñar en grupo, los errores de comunicación entre miembros de equipos pueden conducir a gastar tiempo en reescrituración.
Por otra parte, los lenguajes tradicionales presentan dificultad en la creación de nuevos tipos de datos. Los lenguajes de programación típicamente tienen tipos de datos incorporados: enteros, punto flotante, caracteres, etc. ¿Cómo
crear sus propios tipos de datos?
Los tipos definidos por el usuario y la facilidad para crear tipos abstractos de datos en determinados lenguajes es la
propiedad conocida como extensibilidad. Los lenguajes tradicionales normalmente no son extensibles, y eso hace
que los programas tradicionales sean más complejos de escribir y mantener.
En resumen, con los métodos tradicionales, un programa se divide en dos componentes: procedimientos y datos.
Cada procedimiento actúa como una caja negra. Esto es, es un componente que realiza una tarea específica, tal como
convertir un conjunto de números o visualizar una ventana. Este procedimiento permite empaquetar código programa
en funciones, pero ¿qué sucede con los datos?
Las estructuras de datos utilizadas en programas son con frecuencia globales o se pasan explícitamente como parámetros.
Una forma para aumentar significativamente la productividad del programador consiste en crear un código que se
Página 12
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
pueda reutilizar sin realizar una revisión extensiva y sin volver a probarlo y evaluarlo. La incapacidad del código estructurado en base a procedimientos, para proporcionar su reutilización condujo a la búsqueda de otros enfoques de software.
PROGRAMACION ORIENTADA A OBJETOS
•
Para entender mejor la programación orientada a objetos, haremos un breve estudio sobre las causas fundamentales
que llevaron a cabo la creación de la misma. Podemos resumir como causas principales las siguientes:
‰
‰
‰
La complejidad inherente al software
La crisis del software
Los Factores de la calidad del software
La complejidad inherente al software
•
•
•
A medida que las computadoras se han vuelto más rápidas, baratas y más potentes, se han convertido en herramientas indispensables para científicos e ingenieros.
Quizá lo más importante es que se han vuelto parte de nuestra vida. Sin embargo, tener computadoras rápidas y baratas es sólo la mitad de la ecuación. Aunque ha habido tremendos avances en el campo del hardware, no han existido
avances de la misma magnitud en el diseño de software.
Parte del problema es que las expectativas para el software han crecido considerablemente. La figura 1.11 muestra lo
que se conoce como paradoja de la complejidad: la complejidad del sistema crece a medida que se intenta hacer
más fácil su uso.
Alta
Complejidad total del software
Complejidad
Sencillez para el usuario
Baja
Figura 1.11. A medida que el software es más fácil de usar, se incrementa su complejidad interna.
•
•
Por ejemplo, los primeros sistemas gráficos necesitaban que los usuarios especificaran detalles de cómo debería verse
el gráfico, dando información tan variada como los puntos finales del gráfico, la escala, cómo y dónde habría que colocar las etiquetas.
Esencialmente, el usuario tenía que hacer la mayor parte del trabajo. Actualmente las nuevas herramientas para hojas
de cálculo contienen sistemas expertos, que analizan los datos y producen un gráfico de forma automática. Tales sistemas de representación automática son mucho más fáciles de usar, pero esta facilidad tiene un precio, el incremento
de la complejidad del software.
•
Se dice que la complejidad del software es una propiedad esencial no accidental (¡si hay software, hay complejidad!).
•
Esta complejidad se deriva de dos elementos:
‰
‰
La complejidad del dominio del problema
La dificultad de gestionar el proceso de desarrollo (la interacción entre componentes)
Página 13
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
La complejidad del dominio del problema
•
•
Los problemas a resolver mediante software implican normalmente elementos ineludibles de complejidad, en la que se
encuentran una gran cantidad de requisitos, en muchas ocasiones contradictorios.
Esta complejidad se produce por:
‰
Las difíciles interacciones entre los usuarios de un sistema y sus desarrolladores.
‰
Los usuarios encuentran generalmente muy difícil precisar sus necesidades de forma que los desarrolladores
puedan comprender. En casos extremos los usuarios suelen tener sólo ideas vagas de lo que desean que haga el
sistema.
‰
Los usuarios y desarrolladores tienen diferentes perspectivas de la naturaleza del problema y hacen suposiciones diferentes sobre la naturaleza de la solución. El medio común de expresar los requisitos hoy en día es utilizar un gran volumen de textos, en ocasiones acompañados por esquemas y dibujos. Tales documentos son difíciles de comprender, están abiertos a diferentes interpretaciones y con frecuencia contienen elementos que son diseños en lugar de requisitos esenciales.
‰
Los requisitos de un sistema de software cambian durante su desarrollo. Esto supone que un sistema grande
tiende a evolucionar con el tiempo y el mantenimiento del software en ocasiones es un término que no siempre
está bien acuñado.
‰
Para ser más preciso, existen diferentes términos a definir: El mantenimiento que busca errores; la evolución
que responde a cambios de requisitos y la conservación cuando se utilizan medios para mantener piezas de
software en funcionamiento. Desgraciadamente, la realidad sugiere que un porcentaje alto de los recursos de desarrollo de software se gastan en la conservación del software.
La dificultad de gestionar el proceso de desarrollo
•
•
•
•
•
•
El tamaño de un programa no es una gran virtud en un sistema de software. Sin embargo, la elaboración de un programa de gran dimensión requiere la escritura de grandes cantidades de nuevo software y la reutilización del software
existente.
Recordemos que hace dos o tres décadas los programas en lenguaje ensamblador se construían a base de centenares de líneas. Hoy es usual encontrar sistemas en funcionamiento cuyo tamaño se mide en cientos de miles o incluso
millones de líneas de código.
Esta característica se facilita descomponiendo nuestras implementación en centenares y a veces millones de módulos
independientes.
No es inusual que los programas de aplicación, tales como las hojas de cálculo, procesadores de texto y programas de
dibujo, consten de cientos de miles de líneas de código.
Otro factor que incrementa la complejidad es la interacción entre componentes. Por ejemplo, un procesador de texto
puede contener un componente para corrección ortográfica y otro que proporcione servicios de diccionario de sinónimos.
Consideremos el corrector ortográfico. Cuando se detecta un posible error de ortografía, el corrector debe notificarlo al
usuario. Por lo tanto, el corrector ortográfico, debe relacionarse con el componente de la aplicación que crea una ventana o caja de diálogo, de forma que el posible error pueda mostrarse en pantalla y que se pueda preguntar al usuario
acerca de la acción a ejecutar, si se debe hacer algo. Si el usuario está de acuerdo en que hay un error ortográfico, el
corrector puede corregirlo. Para hacer la corrección, el corrector debe interaccionar con el componente del procesador
de texto responsable de reemplazar texto en el documento. Obviamente, a medida que el número de componentes
crece, el número de interacciones entre componentes crece rápidamente.
Página 14
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
Ingeniería de Software
•
La Ingeniería de Software es el área de la computación que tiene que ver con las técnicas de construcción de software de gran tamaño. El objetivo de un Ingeniero de Software es producir un software que sea:
‰
‰
‰
‰
‰
Fiable.
Comprensible.
Rentable.
Adaptable.
Reutilizable.
Examinemos cada una de estas propiedades.
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
Un software debería ser fiable, es decir, debería funcionar correctamente y sin fallas.
Imagine que ha pasado varias horas escribiendo un texto para un curso en un procesador de textos y, cuando lo tiene
casi terminado, el procesador de textos falla de forma inesperada. Se pierde todo su trabajo. Sin duda, estaría muy enfadado y tendría todo el derecho a estarlo.
Aunque la falla de un procesador de textos es molesta, la pérdida es insignificante comparada con la pérdida potencial
cuando falla un sistema crítico: las vidas humanas.
Un sistema de seguridad crítico es aquel en el que una falla podría significar la pérdida de una vida humana. Ejemplos de este tipo de sistemas son los aviones militares y civiles, las máquinas de terapia radioactiva y los marcapasos.
Una falla del software en cualquiera de estos sistemas podría tener consecuencias desastrosas.
Una forma de conseguir que el software sea más fiable es hacerlo más fácil de comprender o comprensible. Es
decir, lograr que la operación y el diseño del sistema sean fácilmente entendibles por otros profesionales del software.
La comprensibilidad es muy importante porque los software de gran tamaño son construidos por muchas personas
agrupadas en equipos de trabajo.
La construcción del software irá mejor y con menos errores si todo el mundo que trabaja en la aplicación entiende la
operatividad global del sistema y sus componentes.
La comprensibilidad es también muy importante debido a la larga vida del software. Un producto de software suele
evolucionar con el tiempo y a menudo Ingenieros del Software, que no tienen nada que ver con el producto original,
son los que se encargan de introducir mejoras y arreglar los errores del producto.
Este proceso se llama mantenimiento del software. Si la próxima generación de Ingenieros del Software comprende
cómo funciona, las modificaciones de los sistemas complejos, aunque difíciles, se podrán llevar a cabo.
Por el contrario, es extremadamente difícil hacer modificaciones o correcciones para un sistema pobremente diseñado.
A menudo, es más económico reconstruir el sistema desde el principio.
Como medida de la dificultad del mantenimiento del software, los expertos estiman que el 67% del costo de desarrollo
del software se dedica al mantenimiento. Este costo puede reducirse cuando el diseño y el funcionamiento del sistema
son comprensibles.
Por la discusión previa, se puede ver que un software debería ser rentable. Es decir, el costo de desarrollo y mantenimiento del software no debería exceder el beneficio esperado por la venta del producto. Muchas compañías de software han ido a la bancarrota por haber subestimado los costos de desarrollo de un sistema.
Un componente muy relacionado con el costo es el tiempo que se necesita para diseñar y construir el software. Ser el
primero en introducir un producto en el mercado da a una compañía una decidida ventaja sobre sus competidores. Reducir el tiempo para desarrollar un producto puede reducir costos y por lo tanto, incrementar los beneficios.
Debido a la larga vida del software, el software debería ser adaptable. A menudo, es difícil predecir qué características
y capacidades pueden querer los clientes del software. El mantenimiento adaptativo involucra cambios y añadiduras
al software que mejoran la efectividad o competitividad del producto.
Diseñando software al que puedan añadir fácilmente en el futuro nuevas características y capacidades, el Ingeniero del
Software puede reducir los costos de mantenimiento global.
Por el alto costo de desarrollo, el software debería ser reutilizable. Si se ha de gastar muchos millones de dólares en
un software, tiene sentido hacer sus componentes flexibles de forma que puedan ser reutilizados cuando se desarrolle
Página 15
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
un nuevo sistema. Esta estrategia es ciertamente una práctica frecuente en otros negocios. La reutilización puede mejorar la fiabilidad, reducir los costos de desarrollo y mejorar el mantenimiento.
•
•
•
•
•
La cantidad de trabajo que conlleva exige el uso de un equipo de desarrolladores, aunque se trata por todos los medios de que este equipo sea lo más pequeño posible. Ahora bien, a medida que hay mas desarrolladores, se producen
comunicaciones entre ellos mas complejas, e incluso con coordinación difícil entre ellos, particularmente si el equipo
está disperso geográficamente, como suele ser el caso de proyectos grandes.
La descomposición de una aplicación en entidades y relaciones que son significativas a los usuarios es un análisis
convencional con técnicas de diseño.
Con la programación orientada a objetos, este proceso de descomposición se extiende a la fase de implementación.
Es más fácil diseñar e implementar aplicaciones orientadas a objetos, ya que los objetos en el dominio de la aplicación
se corresponden directamente con los objetos en el dominio del software.
Los Ingenieros del Software han desarrollado un cierto número de principios de diseño que ayudan a llevar a cabo
los objetivos marcados en la sección anterior gestionando la inevitable complejidad del software de sistemas grandes,
estos principios son:
Principios de diseño en Ingeniería de Software
‰
‰
‰
Abstracción.
Modularidad.
Encapsulamiento u ocultamiento de la información.
Estos principios de diseño de la Ingeniería de Software ya han sido tratados en otra parte de estas notas, sin embargo, es conveniente
comprender que los tipos abstractos de datos es uno de los conceptos más interesantes de la abstracción; el principio de encapsulamiento
u ocultamiento de la información tiene características mucho más poderosas que las que se realizan en la programación estructurada,
aclaremos un poco más estos conceptos.
•
•
•
•
•
Un Tipo Abstracto de Dato (TAD) es un tipo de dato definido por el programador que se puede manipular de un modo
similar a los tipos de datos definidos por el sistema.
Al igual que los tipos definidos por el sistema, un tipo abstracto de dato corresponde a un conjunto (puede ser de
tamaño indefinido) de valores legales de datos y un número de operaciones primitivas que se pueden realizar sobre
esos valores.
Los usuarios pueden crear variables con valores que están en el rango de valores legales y pueden operar sobre esos
valores utilizando las operaciones definidas.
Por ejemplo, en el caso de una pila se puede definir dicha pila como un tipo abstracto de datos y las operaciones sobre
la pila como las únicas operaciones legales que están permitidas para ser realizadas sobre instancias de la pila.
Los módulos se utilizan frecuentemente como una técnica de implementación para tipos abstractos de datos. El tipo
abstracto de datos es un concepto más teórico. Para construir un tipo abstracto de datos se debe poder:
‰
‰
‰
‰
•
•
Exponer una definición del tipo.
Hacer disponible un conjunto de operaciones que se puedan utilizar para manipular instancias de ese
tipo.
Proteger los datos asociados con el tipo de modo que sólo se pueda actuar sobre ellos con las rutinas
proporcionadas.
Permitir instancias múltiples del tipo.
Los módulos son mecanismos de ocultamiento de información y no cumplen básicamente más que los apartados 1 y 2.
El encapsulamiento u ocultamiento de la información, es el proceso de separar los aspectos de un objeto en externos e internos. Los aspectos externos de un objeto deben ser visibles o conocidos, para otros objetos del sistema. Los
aspectos internos son detalles que no deberían afectar a otras partes del sistema. Ocultar ciertos aspectos de un objeto permite modificarlos sin afectar a otras partes del sistema. Por ejemplo, los aspectos externos del radio de un coche
son los controles y los tipos de conexiones necesarios para conectar el radio al sistema eléctrico, los altavoces y la antena. Los aspectos internos son los detalles del funcionamiento del radio. Para instalar y usar el radio en un coche, no
se necesita conocer nada de ingeniería eléctrica. Esencialmente, el radio puede verse como una caja negra con botones y cables.
Página 16
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
•
•
•
•
•
•
•
•
El encapsulamiento es la propiedad que permite asegurar que el contenido de la información de un objeto está oculta
al mundo exterior: el objeto A no conoce lo que hace el objeto B y viceversa.
El encapsulamiento (también se conoce como ocultamiento de la información), en esencia, es el proceso de ocultar
todos los secretos de un objeto que no contribuyen a sus características esenciales.
El encapsulamiento permite la división de un programa en módulos. Estos módulos se implementan mediante clases,
de forma que una clase representa el encapsulamiento de una abstracción.
En la práctica, esto significa que cada clase debe tener dos partes: un interfaz y una implementación.
El interfaz de una clase captura sólo su vista externa y la implementación contiene la representación de la abstracción,
así como los mecanismos que realizan el comportamiento deseado.
Un gran beneficio del ocultamiento de información es que ayuda a hacer cambios en sistemas complejos. Se puede
reemplazar la radio de un coche por un reproductor de CD sin afectar a otros componentes del vehículo. Debido a que
el manejo de la radio ha sido encapsulado y su vista externa está definida mediante controles y conectores, se puede
quitar el radio viejo, insertar el nuevo y conectarlo.
Cuando se aplica al diseño de sistemas de software, el encapsulamiento permite que se pueda cambiar el comportamiento interno de un componente software sin afectar a otros aspectos del sistema.
Por ejemplo, si el principio de encapsulamiento ha sido aplicado correctamente a un sistema automático de correo de
voz, debería ser capaz de cambiar el componente que se encarga de almacenar los mensajes sin afectar a otras partes del sistema. Se podría incrementar el número de mensajes que un usuario puede almacenar. Si el sistema de almacenamiento de mensajes ha sido debidamente ocultado y aislado, este cambio no debería afectar a la forma en que
los usuarios acceden al sistema y dictan o leen mensajes.
La crisis del software
•
•
•
•
En 1968 una conferencia sobre software, patrocinada por la OTAN, asumió los términos ingeniería del software y
crisis del software. Con estos términos se quería expresar que el software era caro, poco fiable y escaso.
Las metodologías y técnicas estructuradas que han reinado en la década de los setenta y ochenta no han eliminado el
problema, de hecho la crisis del software continúa hoy en día.
Pese a las muchas herramientas y métodos utilizados, los problemas del diseño descendentes permanecen igual,
posiblemente debido a que la complejidad del problema ha crecido considerablemente.
Entre las diferentes fases del ciclo de vida del software (Figura 1.12), el mantenimiento, aunque en otro tiempo fue
despreciada su importancia, se considera actualmente como uno de los problemas más graves en el desarrollo del
software. Muchos investigadores sugieren que los costos del mantenimiento requieren más de la mitad de los costos y
recursos globales del desarrollo total del software.
Análisis
Diseño
Implementación
Depuración
Mantenimiento
Figura 1.12. Ciclo de vida del software
Página 17
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
Análisis
6%
Implementación
7%
Depuración
15 %
Diseño
5%
Mantenimiento
67%
Figura 1.13. Costos de las diferentes fases del ciclo de vida de un proyecto software.
•
•
•
•
Los cambios realizados en la evolución de un programa son el punto débil de los métodos tradicionales de desarrollo
de software, siendo paradójicamente uno de los puntos fuertes de los métodos de desarrollo de software orientado a
objetos.
En 1986, Fredrick P. Brooks, en un famoso artículo, apuntaba que en los últimos diez años no se había producido
ningún progreso significativo en el desarrollo de software, y analizaba críticamente todas las tecnologías más prometedoras. Aunque él confesaba que tenía más confianza en la programación orientada a objetos que en cualquier
otra tecnología, mantenía dudas sobre sus ventajas efectivas.
Recientemente, las propuestas de reusabilidad o reutilización, de componentes software, se consideran como
bloques iniciales para la construcción del programa, de modo similar a la construcción de cualquier objeto complejo (tal
como un automóvil) que se construye ensamblando sus partes.
En respuesta al artículo de Brooks, Brad Cox, el inventor de Objective-C, publicó un artículo en el que esencialmente
rebatía las tesis de Brooks:
Existe una bala de plata. Es un arma tremendamente potente, impulsada por vastas fuerzas económicas a la que nuevos obstáculos técnicos sólo pueden resistir brevemente.
La bala de plata es un cambio cultural en lugar de un cambio tecnológico. Es un nuevo paradigma;
una revolución industrial basada en partes reutilizables e intercambiables que modificarán el universo
del software, de igual modo que la revolución industrial cambió la fabricación.
•
•
Por consiguiente, la POO (Programación Orientada a Objetos) no sólo son nuevos lenguajes de programación, sino un
nuevo modo de pensar y diseñar aplicaciones que pueden ayudar a resolver problemas que afectan al desarrollo del
software.
Sin embargo, el lenguaje debe ser capaz de soportar el nuevo paradigma, siendo por consiguiente una parte esencial
de esta revolución.
Página 18
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
Los factores de la calidad del software
La construcción de software de calidad requiere el cumplimiento de numerosas características. Entre ellas se destacan las siguientes:
•
•
•
•
•
•
•
Eficiencia
La eficiencia del software es su capacidad para hacer un buen uso de los recursos que manipula.
Transportabilidad (portabilidad)
La transportabilidad o portabilidad es la facilidad con la que un software puede ser transportado sobre diferentes sistemas físicos o lógicos.
Verificabilidad
La verificabilidad es facilidad de verificación de un software; es su capacidad para soportar los procedimientos de validación y de aceptar juegos de pruebas o ensayos de programas.
Integridad
La integridad es la capacidad de un software para proteger sus propios componentes contra los procesos que no tengan
derecho de acceso.
Fácil de utilizar
Un software es fácil de utilizar si se puede comunicar con él de manera cómoda.
Corrección
Capacidad de los productos software de realizar exactamente las tareas definidas por su especificación.
Robustez
Capacidad de los productos software de funcionar incluso en situaciones anormales.
•
Extensibilidad
Facilidad que tienen los productos de adaptarse a cambios en su especificación. Existen dos principios fundamentales para conseguir esto:
‰
‰
•
•
diseño simple
descentralización
Reutilización
Capacidad de los productos para ser reutilizados, en su totalidad o en parte, en nuevas aplicaciones.
Compatibilidad
Facilidad de los productos para ser combinados con otros.
Página 19
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
Para poder enfrentar todos los problemas anteriores, así como cumplir con los requerimientos de Ingeniería de sofware y los factores de calidad, se hace necesario el desarrollo de una nueva forma de pensar y de
desarrollar programas, esto se logra con la programación orientada a objetos.
En un determinado sentido, las técnicas orientadas a objetos pueden verse como un producto natural de
una larga progresión histórica que va desde las estructuras de control, pasando por las funciones o procedimientos, los módulos, los tipos abstractos de datos y los objetos ( este último concepto se verá más adelante ).
•
•
La década de los noventa fué, sin lugar a dudas, la década de la programación orientada a objetos. Como Rentsch
predijo, la programación orientada a objetos será en los ochenta lo que la programación estructurada fue en la década
de los setenta.
En la actualidad la programación orientada a objetos se ha hecho enormemente popular. Escritores y diseñadores
de software, junto a compañías importantes en el campo del software, se dedican de modo continuo a producir compiladores de lenguajes, sistemas operativos, bases de datos, etc., orientados a objetos.
¿Qué es la programación orientada a objetos? ¿Por qué es tan popular?
•
•
La programación orientada a objetos es algo más que una colección de lenguajes de programación, tales como Smalltalk, Object Pascal, C++, etc. Se podría decir que este tipo de programación es un nuevo modo de pensar sobre lo que
significa computar (computarizar), es decir, cómo se puede estructurar información en una computadora.
Grady Booch, autor del méto Booch de diseño orientado a objetos muy popular en la década de los noventa, creador
de la empresa Racional – fabricante de la herramienta Rose para ingeniería de software orientada a objetos - e impulsor del lenguaje unificado de modelado UML, define la programación orientada a objetos (POO) como:
ƒ Un método de implementación en el que los programas se organizan como colecciones cooperativas de objetos, cada uno de los cuales representan una
instancia de alguna clase, y cuyas clases son todas miembros de una jerarquía de clases unidas mediante relaciones de herencia.
•
•
•
•
•
•
•
•
•
•
Existen tres importantes partes en la definición: la programación orientada a objeteos 1) utiliza objetos, no algoritmos,
como bloques de construcción lógicos (jerarquía de objetos); 2) cada objeto es una instancia de una clase, y 3) las clases se relacionan unas con otras por medio de relaciones de herencia.
Algunos autores de libros aún recuerdan la gran frustración que sentían las empresas de desarrollo de software, especialmente aquellas que desarrollaban proyectos a gran escala, como por ejemplo, el desarrollo de sistemas operativos
con tiempo compartido y memoria virtual. La realidad llegaba cuando la empresa decidía producir de manera comercial
el sistema en el que cientos de personas habían trabajado durante muchos años. Era difícil poner a punto este software. El software es un asunto complejo.
Las mejoras a la tecnología de software comenzaron a aparecer con los beneficios de la denominada programación
estructurada (y las disciplinas relacionadas como el análisis y diseño de sistemas estructurados) que se realizaba en
la década de los setenta.
Pero no fue hasta que la tecnología de la programación orientada a objetos se hizo popular en la década de los
noventa, que los desarrolladores de software sintieron que tenían las herramientas necesarias para realizar mayores
adelantos en el proceso de desarrollo de software.
Antes de la aparición de los lenguajes orientados a objetos, los lenguajes de programación (tales como FORTRAN,
Pascal, Basic y C) se basaban en acciones (verbos), en lugar de cosas u objetos (sustantivos).
Los programadores, que viven en un mundo de objetos, programan primordialmente mediante el uso de verbos. Este
cambio de paradigma complicó la escritura de programas. Ahora, con la disponibilidad de los lenguajes orientados a
objetos tales como Java y C++, los programadores siguen viviendo en un mundo orientado a objetos y pueden programar de una manera orientada a objetos.
Éste es un proceso más natural de programación y ha dado como resultado un mayor grado de productividad.
Un problema fundamental con la programación basada en procedimientos es que las unidades de programación no
reflejan de manera fácil y efectiva a las entidades del mundo real; así, estas unidades no son particularmente reutilizables.
Con gran frecuencia los programadores deben comenzar de nuevo cada nuevo proyecto y escribir código similar desde
cero: esto significa gasto de tiempo y de dinero, ya que tiene que reinventar las cosas repetidamente.
Mediante la tecnología de objetos, las entidades de software creadas (llamadas clases), si se diseñan apropiadamente
tienden a ser mucho más reutilizables en proyectos futuros.
Página 20
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
•
•
•
•
•
•
•
•
Con las bibliotecas de componentes reutilizables, tales como la MFC (Microsoft Foundation Classes) y las creadas por
Rogue Wave y muchas otras empresas desarrolladoras de software, se puede reducir la cantidad del esfuerzo requerido para implementar ciertas clases de sistemas (comparadas con el esfuerzo que se hubiera requerido para reinventar
estas capacidades en nuevos proyectos).
Algunas empresas indican que la reutilización de software no es, de hecho, el principal beneficio que obtienen de la
programación orientada a objetos. Más bien, mencionan que la programación orientada a objetos tiende a producir
software que es más comprensible, mejor organizado y fácil de mantener, modificar y corregir.
Esto puede ser importante debido a que se estima que el 80% de los costos de software no están asociados con los
esfuerzos originales para el desarrollo de software, están asociados con la continua evolución y mantenimiento de ese
software durante su vida útil.
Cualesquiera que sean los beneficios que se perciban de la programación orientada a objetos, es claro que ésta será
la metodología clave de la programación para las siguientes décadas.
La desventaja es el tiempo y esfuerzos que implica el diseño e implementación de nuevo código.
La orientación a objetos fuerza a reconsiderar nuestro pensamiento sobre la computación, sobre lo que significa realizar computación y sobre cómo se estructura la información dentro de la computadora.
Jenkins y Glasgow observan que «la mayoría de los programadores trabajan en un lenguaje y utilizan sólo un estilo de
programación. Ellos programan en un paradigma forzado por el lenguaje que utilizan. Con frecuencia, no se enfrentan
a métodos alternativos de resolución de un problema, y por consiguiente tienen dificultad en ver la ventaja de elegir un
estilo más apropiado al problema a manejar».
Bobrow y Stefik definen un estilo de programación como «un medio de organización de programas sobre la base de
algún modelo conceptual de programación y un lenguaje apropiado para hacer programas en un estilo claro». Sugieren
que existen cuatro clases de estilos de programación:
‰
‰
‰
‰
•
Orientados a procedimientos
Orientados a objetos
Orientados a lógica
Orientados a reglas
Algoritmos
Clases y objetos
Expresado en cálculo de predicados
Reglas If-then
No existe ningún estilo de programación idóneo para todas las clases de programación. La orientación a objetos se
acopla a la simulación de situaciones del mundo real.
¿Qué son los objetos y por qué son tan especiales?
•
•
•
•
•
En realidad, la tecnología de objetos es un esquema de compactación que permite crear unidades útiles de software.
Existen objetos de datos, de tiempo, de cheques, de facturas, de audio, vídeo, de archivo, de registro, y otros más. De
hecho, casi cualquier sustantivo puede representarse razonablemente como un objeto.
Vivimos en un mundo de objetos. Sólo mire a su alrededor. Existen automóviles, aviones, gente, animales, edificios,
semáforos, elevadores, y otras cosas.
Desde el enfoque de un TAD, un objeto es, sencillamente, un tipo abstracto de dato al que se añaden importantes
innovaciones en lo referente a compartir código y la reutilización. Los objetos son tipos de datos que encapsulan con el
mismo nombre estructuras de datos y las operaciones o algoritmos que manipulan esos datos.
Los mecanismos básicos de orientación a objetos son: objetos, mensajes y métodos, clases e instancias, herencia y persistencia.
•
Una idea fundamental es la comunicación de los objetos a través de paso de mensajes.
•
Además de esta idea se añaden los mecanismos de herencia y polimorfismo.
•
•
•
La herencia permite diferentes tipos de datos para compartir el mismo código, permitiendo una reducción en el tamaño
del código y un incremento en la funcionalidad.
El polimorfismo permite que un mismo mensaje pueda actuar sobre objetos diferentes y comportarse de modo distinto.
La persistencia se refiere a la permanencia de un objeto, esto es, la cantidad de tiempo para el cual se asigna espacio y permanece accesible en la memoria del computador.
Página 21
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
Conceptos clave
Abstracción
Encapsulación
Persistencia
Herencia
Polimorfismo
Genericidad
Entidades básicas
Objeto
Mensajes,
Métodos
Clases,
Instancias
Herencia,
Jerarquía
Figura 1.9. Principios básicos de la orientación a objetos.
Razones fundamentales que están influyendo en la importancia de la POO
•
•
•
•
•
•
Algunas de las causas que están influyendo considerablemente en el notable desarrollo de las técnicas orientadas a
objetos son:
‰
La POO (Orientación a Objetos) es especialmente adecuada para realizar determinadas aplicaciones, sobre todo
realización de prototipos y programas de simulación.
‰
Los mecanismos de encapsulamiento de la POO soportan un alto grado de reutilización de código, que se incrementa por sus mecanismos de herencia.
‰
En el entorno de las bases de datos, la POO se adjunta bien a los modelos semánticos de datos para solucionar las
limitaciones de los modelos tradicionales, incluido el modelo relacional.
‰
Aumento espectacular de LPOO (Lenguajes de Programación Orientada a Objetos).
‰
Interfaces de usuario gráficos (por iconos) y visuales. Los interfaces de usuario de una aplicación manipulan la
entrada y salida del usuario. Por consiguiente, su función principal es la comunicación con el usuario final. La entrada al sistema se puede controlar a través de líneas de órdenes (enfoque utilizado por DOS y UNIX), o alternativamente el usuario puede interactuar con el sistema, con construcciones de programación visuales, tales como
iconos de menús, Windows, Macintosh, etc.
Estas razones hacen fundamentalmente que dentro de las tendencias actuales de la ingeniería de software, el marco
de POO se revela como el más adecuado para la elaboración del diseño y desarrollo de aplicaciones.
Esté marco se caracteriza por la utilización del diseño modular OO y la reutilización del software.
Los TAD (Tipo Abstracto de Dato) han aumentado la capacidad para definir nuevos tipos (clases) de objetos, cuyo
significado se definirá abstractamente, sin necesidad de especificar los detalles de implementación, tales como la estructura de datos a utilizar para la representación de los objetos definidos.
Los objetos pasan a ser los elementos fundamentales en este nuevo marco, en detrimento de los subprogramas que lo
han sido en los marcos tradicionales.
Introduciremos también otras unidades de programación estructurada llamadas clases. Después, crearemos objetos a
partir de clases y procederemos con nuestra explicación acerca de la programación orientada a objetos.
Página 22
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
1.2 Conceptos fundamentales de la Programación Orientada a Objetos
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
Comenzaremos nuestra introducción a la orientación a objetos. Veremos que la orientación a objetos es una manera
natural de pensar acerca del mundo real y de escribir programas de cómputo.
En esta sección introduciremos los conceptos básicos, es decir, pensar en objetos y la terminología, es decir, hablar
de objetos.
Comenzaremos nuestra introducción a la programación orientada a objetos con la terminología clave de ésta.
Mire a su alrededor en el mundo real. Por donde quiera que voltee los puede ver, ¡objetos!, gente, animales, plantas,
automóviles, edificios, computadoras, etcétera.
Los humanos pensamos en términos de objetos. Tenemos la maravillosa habilidad de abstracción que nos permite
ver imágenes en pantalla como objetos tales como gente, aviones, árboles y montañas, en lugar de puntos individuales
de color. Podemos, si lo deseamos, pensar en términos de playas en vez de granos de arena, bosques en vez de árboles y casas en lugar de ladrillos.
Quizá nos inclinemos a dividir los objetos en dos categorías: objetos animados y objetos inanimados. Los objetos
animados están vivos de alguna manera. Se mueven y hacen cosa. Los objetos inanimados, como las toallas, parecen
no hacer nada en absoluto. Parecen que sólo están ahí.
Sin embargo, todos los objetos tienen algo en común, todos tienen atributos, como tamaño, forma, color, peso, etcétera, que los describen.
Todos exhiben un comportamiento, o realizan operaciones (por ejemplo, una bola rueda, rebota, se infla y se desinfla; un bebé llora, duerme, gatea, camina y parpadea; un automóvil acelera, frena y gira; una toalla absorbe agua, etcétera) que especifican lo que hacen.
Los humanos aprendemos de los objetos al estudiar sus atributos y al observar su comportamiento.
Objetos diferentes pueden tener atributos similares y comportamiento similares. Por ejemplo, se pueden hacer comparaciones entre bebés y adulto, y entre humanos y chimpancés. Los automóviles, camiones, vagones y patinetas tienen
mucho en común.
La programación orientada a objetos (POO) toma como modelo a los objetos reales para elaborar su contraparte en
software.
Toma ventaja de las relaciones entre clases, en donde objetos de cierta clase, tal como una clase de vehículos, tiene
atributos y operaciones similares.
Toma ventaja de las relaciones de herencia e incluso de las relaciones de herencia múltiple, en donde las nuevas
clases de objetos creadas se derivan mediante la absorción de atributos y operaciones de clases existentes y mediante
la adición de sus propias características únicas.
Un objeto de la clase convertible ciertamente tiene las características de la clase más general automóvil, pero el
techo del convertible puede quitarse o ponerse.
La programación orientada a objetos nos brinda una forma natural de ver el proceso de programación, a saber, mediante el modelado de objetos reales, sus atributos y comportamiento. La programación orientada a objetos proporciona también comunicación entre los objetos. Tal como las personas se envían mensajes entre sí (por ejemplo, un sargento que le ordena a un soldado que se coloque en posición de firmes), los objetos también se comunican mediante
mensajes.
La programación orientada a objetos encapsula datos (atributos) y funciones (operaciones) en paquetes llamados
objetos; los datos y las funciones de un objeto están íntimamente ligados.
Los objetos tienen la propiedad de ocultar información. Esto significa que aunque los objetos pueden saber cómo
comunicarse con otros a través de interfaces bien definidas, por lo general, los objetos no saben cómo se implementan otros objetos, los detalles de implementación se ocultan dentro de los mismos objetos. Con seguridad, es posible
manejar un automóvil de manera efectiva sin tener que conocer a fondo los detalles de cómo funcionan internamente
los sistemas del motor y la transmisión.
Página 23
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
•
•
•
•
•
•
•
•
También, veremos por qué el ocultamiento de información es crucial para la buena ingeniería de software.
En C y otros lenguajes de programación por procedimientos, la programación tiende a ser orientada a acciones;
mientras que en C++, la programación tiende a ser orientada a objetos.
En C, la unidad de programación es la función. En C++, la unidad de programación es la clase, a través de la cual se
obtienen las instancias.
En C++, las clases contienen funciones que implementan el comportamiento y datos que implementan los atributos de
la clase.
Los programadores de C se concentran en escribir funciones. Los programadores agrupan acciones dentro de funciones que realizan alguna tarea común y agrupan funciones para formar programas.
Ciertamente, los datos son importantes en C, pero la idea es que los datos existen primordialmente para apoyar las
acciones que realizan las funciones.
Los verbos en una especificación de sistema ayudan al programador en C a determinar un conjunto de funciones que
trabajan juntas para implementar el sistema.
Los programadores en C++ se concentran en crear sus propios tipos definidos por el usuario llamados clases y componentes.
•
Cada clase contiene datos, así como un conjunto de funciones que manipulan esos datos.
•
En C++, a los componentes de datos de una clase se les llama dato miembro.
•
•
•
•
•
•
•
•
•
•
En C++, a las funciones que componen una clase se les llama funciones miembro (por lo general, en otros lenguajes
de programación orientados a objetos, como Java, se les denomina métodos).
Tal como a una instancia de un tipo predefinido como int se le llama variable, a una instancia de un tipo definido por el
usuario (es decir, una clase) se le llama objeto.
El programador utiliza tipos predefinidos (y otros tipos definidos por el usuario) como bloques de construcción, para
construir tipos definidos por el usuario (clases).
El foco de atención en C++ se centra en las clases (desde las que se crean los objetos) en vez de funciones. Los
sustantivos en una especificación de sistema ayudan al programador en C++ a determinar el conjunto de clases desde el que se crean los objetos que trabajan juntos para implementar un sistema.
Las clases son a los objetos lo que los planos son a las casas. Podemos construir muchas casas a partir de un plano, y
podemos crear instancias de muchos objetos a partir de una clase. Además, las clases pueden tener relación con
otras clases.
Por ejemplo, en el diseño orientado a objetos de un banco, la clase CajeroBanco necesita relacionarse con la clase
CuentaBanco. La más simple de estas relaciones se denomina asociación.
Veremos que el software empaquetado como clases puede reutilizarse en futuros sistemas de software. A menudo,
grupos de clases relacionadas se empaquetan como componentes reutilizables.
La orientación a objetos puede describirse como el conjunto de disciplinas (ingeniería) que desarrollan y modelan software que facilitan la construcción de sistemas complejos a partir de componentes.
El atractivo intuitivo de la orientación a objetos es que proporciona conceptos y herramientas con las cuales se modela y representa el mundo real tan fielmente como sea posible.
Las ventajas de la orientación a objetos son muchas en programación y modelado de datos. Como apuntaban Ledbetter y Cox (1985):
‰
La programación orientada a objetos permite una representación más directa del modelo de mundo real en el código.
El resultado es que la radicalmente transformación normalmente llevada a cabo de los requisitos del sistema (definido en términos de usuario) a la especificación del sistema (definido en términos de computadora) se reduce considerablemente.
Página 24
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
•
•
La Figura 1.15 ilustra el problema. Utilizando técnicas convencionales, el código generado para un problema del mundo real consta de una primera codificación del problema y, a continuación, la transformación del problema en términos
de un lenguaje de computadora Von Newmann.
Las disciplinas y técnicas orientadas a objetos manipulan la transformación automáticamente, de modo que el volumen
de código del problema y la transformación se minimiza. De hecho, cuando se compara con estilos de programación
convencionales (procedimentales, o por procedimientos), las reducciones de código van desde un 40% hasta un orden
de magnitud elevado cuando se adopta un estilo de programación orientado a objetos.
Problemas del
mundo real
Transformación de Von Newmann
Programa
Codificación del programa
Figura 1.15. Construcción de software
•
•
•
•
•
Los conceptos y herramientas orientados a objetos son tecnologías que permiten que los problemas del mundo real
sean expresados de modo fácil y natural.
Las técnicas orientadas a objetos proporcionan mejoras y metodologías para construir sistemas de software complejos
a partir de unidades de software modularizado y reutilizable.
Se necesita un nuevo enfoque para construir software en la actualidad. Este nuevo enfoque debe ser capaz de manipular tanto sistemas grandes como pequeños y debe crear sistemas fiables que sean flexibles, mantenibles y capaces
de evolucionar para cumplir las necesidades de cambio.
La tecnología orientada a objetos puede cubrir estos cambios y algunos otros más en el futuro.
La orientación a objetos trata de cumplir las necesidades de los usuarios finales, así como las propias de los desarrolladores de productos software. Estas tareas se realizan mediante la modelización del mundo real. El soporte fundamental es el modelo objeto. Las propiedades más importantes de este modelo son:
‰
‰
‰
‰
‰
‰
•
Abstracción
Encapsulamiento
Modularidad
Jerarquía
Polimorfismo
Otras propiedades: concurrencia (multitarea), persistencia, genericidad, manejo de excepciones.
Como sugiere Booch, si alguno de estos elementos no existe se dice que el modelo no es orientado a objetos.
Como algunos de estos temas ya han sido tratados (abstracción, encapsulamiento, modularidad, jerarquía ), no lo
haremos aquí, salvo que se quisiera agregar algun comentario extra.
Página 25
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
Jerarquía
•
•
•
•
•
La jerarquía es una propiedad que permite una ordenación de las abstracciones.
Las dos jerarquías más importantes de un sistema complejo son: estructura de clases (jerarquía «es-un» (is-a):
generalización/especialización) y estructura de objetos (jerarquía «parte-de» (part-of): agregación).
No se debe confundir clases y objetos de la misma clase: un coche rojo y un coche azul no son objetos de clases
diferentes, sino objetos de la misma clase con un atributo diferente.
Las jerarquías de generalización/especialización se conocen como herencia. Básicamente, la herencia define una
relación entre clases, en donde una clase comparte la estructura o comportamiento definido en una o más clases
(herencia simple y herencia múltiple, respectivamente).
La agregación es el concepto que permite el agrupamiento físico de estructuras relacionadas lógicamente. Así, un
camión se compone de ruedas, motor, sistema de transmisión y chasis; en consecuencia, camión es una agregación,
y ruedas, motor, transmisión y chasis son agregados de camión.
Polimorfismo
•
•
•
•
•
•
•
•
•
•
•
•
La quinta propiedad significativa de los lenguajes de programación orientados a objetos es el polimorfismo. Esta
propiedad no suele ser considerada como fundamental en los diferentes modelos de objetos propuestos, pero dada su
importancia, no tiene sentido considerar un modelo objeto que no soporte esta propiedad.
Polimorfismo es la propiedad que indica, literalmente, la posibilidad de que una entidad tome muchas formas.
En términos prácticos, el polimorfismo permite referirse a objetos de clases diferentes mediante el mismo elemento
de programa y realizar la misma operación de diferentes formas, según sea el objeto que se referencia en ese momento.
Por ejemplo, cuando se describe la clase mamíferos se puede observar que la operación comer es una operación
fundamental en la vida de los mamíferos, de modo que cada tipo de mamífero debe poder realizar la operación o función comer. Por otra parte, una vaca o una cabra que pastan en un campo, un niño que se come un bombón o caramelo y un león que devora a otro animal, son diferentes formas que utilizan los distintos mamíferos para realizar la
misma función (comer).
El polimorfismo implica la posibilidad de tomar un objeto de un tipo (mamífero, por ejemplo) e indicarle que ejecute
comer; esta acción se ejecutará de diferente forma, según sea el objeto mamífero sobre el que se aplica.
Clases, herencia y polimorfismo son aspectos claves en la programación orientada a objetos y se reconocen a estos
elementos como esenciales en la misma.
El polimorfismo adquiere su máxima expresión en la derivación o extensión de clases, es decir, cuando se obtiene
una clase a partir de una clase ya existente, mediante la propiedad de derivación de clases o herencia.
Así, por ejemplo, si se dispone de una figura que represente figuras genéricas, se puede enviar cualquier mensaje,
tanto a un tipo derivado (elipse, círculo, cuadrado, etc.) como al tipo base. Por ejemplo, una clase figura puede aceptar
los mensajes dibujar, borrar y mover. Cualquier tipo derivado de una figura es un tipo de figura y puede recibir el
mismo mensaje.
Cuando se envía un mensaje, por ejemplo dibujar, esta tarea será distinta según que la clase sea un triángulo, un
cuadrado o una elipse. Esta propiedad es el polimorfismo, que permite que una misma función se comporte de diferente forma según sea la clase sobre la que se aplica.
La función dibujar se aplica igualmente a un círculo, a un cuadrado o a un triángulo y el objeto ejecutará el código
apropiado dependiendo del tipo específico.
El polimorfismo requiere ligadura tardía o postergada (también llamada dinámica), y esto sólo se puede producir
en lenguajes de programación orientados a objetos.
Los lenguajes no orientados a objetos soportan ligadura temprana o anterior; esto significa que el compilador genera
una llamada a un nombre específico de función y el enlazador (linker) resuelve la llamada a la dirección absoluta del
código que se ha de ejecutar.
Página 26
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
•
•
•
•
En POO, el programa no puede determinar la dirección del código hasta el momento de la ejecución; para resolver
este concepto, los lenguajes orientados a objetos utilizan el concepto de ligadura tardía.
Cuando se envía un mensaje a un objeto, el código que se llama no se determina hasta el momento de la ejecución. El
compilador asegura que la función existe y realiza verificación de tipos de los argumentos y del valor de retorno, pero
no conoce el código exacto a ejecutar.
Para realizar la ligadura tardía, el compilador inserta un segmento especial de código en lugar de la llamada absoluta.
Este código calcula la dirección del cuerpo de la función para ejecutar en tiempo de ejecución utilizando información
almacenada en el propio objeto. Por consiguiente, cada objeto se puede comportar de modo diferente de acuerdo al
contenido de ese puntero. Cuando se envía un mensaje a un objeto, éste sabe qué ha de hacer con ese mensaje.
Otras propiedades
•
El modelo objeto ideal no sólo tiene las propiedades anteriormente citadas, sino que es conveniente que soporte,
además, estas otras propiedades:
‰
‰
‰
‰
•
•
Concurrencia (multitarea).
Persistencia
Genericidad
Manejo de excepciones
Algunos lenguajes soportan todas estas propiedades y otros sólo algunas de ellas. Así, por ejemplo, Ada soporta
concurrencia y Ada y C++ soportan genericidad y manejo de excepciones.
La persistencia o propiedad de que las variables -y por extensión los objetos- existan entre las invocaciones de un
programa es posiblemente la propiedad menos implantada en los LPOO, aunque ya es posible considerar la persistencia en lenguajes tales como Smalltalk y C++, lo que facilitará el advenimiento de las bases de datos orientadas a objetos, como así está sucediendo.
REUTILlZACIÓN DE SOFTWARE
•
•
•
•
•
•
•
•
Cuando se construye un automóvil, un edificio o un dispositivo electrónico, se ensamblan una serie de piezas independientes, de modo que estos componentes se reutilicen, en vez de fabricarlos cada vez que se necesita construir un
automóvil o un edificio.
En la construcción de software, esta pregunta es continua. ¿Por qué no se utilizan programas ya construidos para
formar programas más grandes? Es decir, si en electrónica los computadores y sus periféricos se forman esencialmente con el ensamblado de circuitos integrados, ¿existe algún método que permita realizar grandes programas a partir de
la utilización de otros programas ya realizados? ¿Es posible reutilizar estos componentes de software?
Las técnicas orientadas a objetos proporcionan un mecanismo para construir componentes de software reutilizables
que posteriormente puedan ser interconectados entre sí y formar grandes proyectos de software.
En los sistemas de programación tradicionales y en particular en los basados en lenguajes de programación estructuradas (tales como FORTRAN, C, etc.), existen las bibliotecas de funciones, que contienen funciones (o procedimientos,
según el lenguaje) que pueden ser incorporados en diferentes programas.
En sistemas orientados a objetos se pueden construir componentes de software reutilizables, al estilo de las bibliotecas de funciones, normalmente denominados bibliotecas de software o paquetes de software reutilizables.
Ejemplos de componentes reutilizables comercialmente disponibles son: Turbo Visión de Turbo Pascal, OLE 2.0 de
C++, jerarquía de clases Smalltalk, clases MacApp para desarrollo de interfaces gráficos de usuario en Object Pascal,
disponibles en Apple, la colección de clases de Objective-C, etc.
En el futuro inmediato, los ingenieros de software dispondrán de catálogos de paquetes de software reutilizable, al
igual que sucede con los catálogos de circuitos integrados electrónicos, como les ocurre a los ingenieros de hardware.
Las técnicas orientadas a objetos ofrecen una alternativa de escribir el mismo programa una y otra vez. El programador orientado a objetos modifica una funcionalidad del programa sustituyendo elementos antiguos u objetos por nuevos
objetos, o bien conectando simplemente nuevos objetos en la aplicación.
Página 27
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
•
•
La reutilización de código en programación tradicional se puede realizar copiando y editando, mientras que en programación orientada a objetos se puede reutilizar el código, creando automáticamente una subclase y anulando alguno de sus métodos.
Muchos lenguajes orientados a objetos fomentan la reutilización mediante el uso de bibliotecas robustas de clases
preconstruidas, así como otras herramientas, como hojeadores (browser), para localizar clases de interés y depuradores interactivos para ayudar al programador.
Página 28
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
1.2.1 Los lenguajes orientados a objetos
La evolución de los LPOO
•
•
•
•
•
Al principio de la década de los sesenta, Kristen Nygaard y Ole-Johan Dhal desarrollaron Simula en el Norwegian
Computer Center (NCC), un lenguaje que soportaba modelado por simulación de procesos industriales y científicos.
Fue un lenguaje de propósito general que ofrecía capacidad de simulación de sistemas. Sin embargo, sus usuarios
descubrieron pronto que Simula proporcionaba nuevas y poderosas posibilidades para fines distintos de la simulación,
como la elaboración de prototipos y el diseño de aplicaciones.
Las sucesivas versiones de Simula fueron mejorándose hasta llegar a Simula-67 (aparición en diciembre de 1966).
Simula-67 se derivaba de Algol 60, donde tiene sus raíces, y se diseñó fundamentalmente como un lenguaje de programación de diseño; tomó de Algol el concepto de bloque e introdujo el concepto de objeto.
Los objetos de Simula tenían su propia existencia y podían comunicarse entre sí durante un proceso de simulación.
Conceptualmente, un objeto contenía tanto datos como las operaciones que manipulaban esos datos. Las operaciones
se llamaron métodos. Simula incorporaba también la noción de clases, que se utilizaron para describir la estructura y
comportamiento de un conjunto de objetos. La herencia de clases fue también soportada por Simula. La herencia organiza las clases en jerarquías, permitiendo compartir implementación y estructura.
En esencia, Simula sentó la base de los lenguajes orientados a objetos y definió algunos de los conceptos clave de la
orientación a objetos. Además, Simula era un lenguaje fuertemente tipificado. Esto significa que el tipo de cada variable se conoce en tiempo de compilación, de modo que los errores que implican tipos se encuentran en esta etapa y
no cuando el programa se ejecuta.
Simula-67 fue el primer lenguaje de programación que incorporó mecanismos para soportar los conceptos orientados
a objetos más sobresalientes:
‰
‰
‰
‰
‰
•
Encapsulamiento y objetos, que agrupan juntos atributos de datos y acciones (métodos) que procesen esos datos.
Verificación estática de tipos, que se realiza durante el proceso de compilación para proporcionar seguridad en tiempo de ejecución para la manipulación externa de los atributos de los objetos.
Clases, como plantillas o patrones de objetos.
Herencia, como medio de agrupar clases con propiedades comunes.
Ligadura dinámica (polimorfismo), para permitir a las clases de objetos que tengan interfaces idénticos y propiedades
que se puedan intercambiar.
La Figura 1.16 muestra la evolución (genealogía) de los lenguajes de programación orientados a objetos (LPOO). En
esta figura se muestra que Simula-67 (Simula) inspiró el desarrollo de Smalltalk, que es el verdadero primer lenguaje
de programación orientado a objetos.
Página 29
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
Figura 16. Genealogía de los lenguajes de objetos según Sebesta
Página 30
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
•
•
•
•
•
•
•
•
Alan Kay creó Smalltalk-80 en Xerox PARC (Xerox Palo Alto Research Park) con Adele Goldberg, que previamente
había trabajado con una implementación de Simula. Smalltalk es un lenguaje orientado a objetos puro, «todos es un
objeto» de una clase y todas las clases heredan de una única clase base denominada Object. Smalltalk afirmó el
término «método» para describir las acciones realizadas por un objeto y el concepto de «paso de mensajes» como el
medio para activar «métodos». Es también un lenguaje tipificado dinámicamente, que liga (enlaza) un método a un
mensaje en tiempo de ejecución.
Smalltalk ha sido, a su vez, el inspirador de un gran número de lenguajes OO. Entre ellos destaquemos Eiffel, Smalltalk-80, Smalltalk/V, C++, Actor, Objective-C y CLOS, así como extensiones OO de lenguajes tradicionales, tales
como Object Pascal, Object COBOL, etc.
Bertran Meyer, el diseñador de Eiffel, fue también un usuario de Simula, e incluso llegó a ser presidente de la Asociación de Usuarios de Simula.
Jean Ichbiah, el diseñador jefe de Ada-83, dirigió un equipo que implementó un subconjunto de Simula, y Bjarne
Stroustrup, el diseñador de C++, utilizó Simula y siempre ha agradecido su influencia en el diseño de C++.
Existen varias versiones y dialectos de Smalltalk: Smalltalk- 72, -74, -76, -78, -80 y más recientemente -y seguramente la más popular- Smalltalk/V de Digitalk.
Smalltalk no es un lenguaje tipificado. Smalltalk es extraordinariamente rico en conceptos orientados a objetos. En
Smalltalk todo es un objeto, incluyendo clases base y tipo base. Esto significa que la potencia de Smalltalk, como un
entorno de programación completo, se fundamenta en el envío de mensajes a objetos.
Otra característica fundamental que diferencia a Smalltalk es su capacidad de concurrencia. La concurrencia es un
aspecto del mundo real. Por ejemplo, en un entorno de oficina, secretarias, administrativos, gerentes y otros empleados funcionan simultánea e independientemente. Se comunican entre sí, a través de conversaciones, informes, correo
electrónico, etc. Smalltalk empleó la construcción denominada proceso para soportar concurrencia.
Durante la década de los ochenta, los conceptos orientados a objetos (tipos abstractos de datos, herencia, identidad
de objetos y concurrencia), Smalltalk, Simula y otros lenguajes comenzaron a mezclarse y producir nuevos lenguajes
orientados a objetos, así como extensiones y dialectos. El desarrollo de lenguajes de orientación a objetos en esa
década se muestra en la siguiente clasificación:
‰
Extensiones, dialectos y versiones de Smalltalk. Xerox y Textronix incorporaron en sus máquinas, a principios de los
ochenta, la versión Smalltalk-80, que posteriormente se fue incorporando a otras muchas plataformas. Digitalk
lanzó Smalltalk/V para computadoras personales IBM y compatibles.
‰
Extensiones orientadas a objetos de lenguajes convencionales. Uno de los lenguajes orientados a objetos más populares es C++. Este lenguaje fue diseñado por Bjarne Stroustrup en AT &T al principio de los ochenta [Stroustrup,
1986]. La primera implementación del lenguaje C++ se lanzó como un preprocesador a los compiladores C. C++ proporcionó dos construcciones para definiciones de clases. El primer método es una extensión de la construcción struct
(estructura de C) y la otra nueva construcción class (clase). C++ incorporó jerarquía de clases y permitía subclases
que podían acceder a métodos y variables instancias de otras clases de su jerarquía. El lenguaje C++ permitía la ligadura dinámica y el polimorfismo, así como sobrecarga de funciones y operaciones. Sin embargo, al contrario que
Smalltalk, las primeras versiones de C++ no comercializaban bibliotecas grandes de clases predefinidas.
Otro dialecto importante de C++, con propiedades orientadas a objetos, es Objective-C [Cox 1987]. Este lenguaje es
un superconjunto de C, que incorpora características orientadas a objetos de Smalltalk.
Al igual que Smalltalk, Objective-C incluía una gran colección de clases predefinidas que permitía simplificar el proceso de desarrollo. Objective-C soportaba tipos abstractos de datos, herencia y sobrecarga de operadores. Sin embargo, al contrario que C++, no ampliaba la definición de construcciones existentes en lenguajes, y diseñó nuevas construcciones y operadores para realizar tareas tales como definición de clases y paso de mensajes. Las computadoras
NEXT, cuyo éxito no pasó de unos años, eligieron Objective-C como su principal lenguaje de desarrollo.
Niklaus Wirth y un grupo de ingenieros informáticos de Apple Computer diseñaron Object Pascal [Schmucker,
1986]. Extendió el lenguaje Pascal con soporte para tipos abstractos de datos, métodos y herencia. Incluyó el concepto de tipo de objeto y definición de clases.
Los nuevos lenguajes Ada-95 y Java son totalmente orientados a objetos.
Página 31
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
‰
Lenguajes orientados a objetos fuertemente tipificados. Simula fue uno de los lenguajes orientados a objetos que se
desarrollaron en la década de los ochenta y que fueron implementados en diversas plataformas.
Otros lenguajes han emergido en la década de los ochenta, con características fuertemente tipificadas (con verificación estricta de tipos). Un lenguaje disponible comercialmente y muy interesante es Eiffel [Meyer, 1988] de Interactive Software Engineering, Inc. Además de encapsulamiento y herencia, Eiffel incorpora muchas características
orientadas a objetos, tales como tipos paramétricos y pre y post-condiciones para métodos. Otro lenguaje fuertemente
tipificado que soporta conceptos orientados a objetos (abstracción, objetos, tipos paramétricos) es Ada, aunque la
versión Ada-83 presenta el inconveniente de no soportar herencia.
‰
Extensiones orientadas a objetos de LlSP. Existen diferentes versiones de LISP, aunque la más conocida y notable
es CLOS (Common List Object System). CLOS es un lenguaje OO que introduce notables mejoras y tiene garantizada larga vida, especialmente desde la creación del comité X3J13 de ANSI para la estandarización del lenguaje.
Estado de los lenguajes orientados a objetos en la década de los noventa
•
•
•
•
•
•
La década de los ochenta lanzó la orientación a objetos como base de la futura ingeniería de software orientada a
objetos de la década de los noventa. En 1982 se predijo que la programación orientada a objetos sería en la década de
los ochenta lo que la programación estructurada fue en los setenta (Rentsch, 1982). La profecía se cumplió y la década
de los ochenta se consagró como el origen de la explosión de la orientación a objetos que se produciría en la década
de los noventa.
Sin duda, el desarrollo de conferencias internacionales sobre orientación a objetos y, en especial, OOPSLA (ObjectOriented Programming Systems and LAnguages) han sido los detonantes de la explosión de la OO en la década de los
noventa. La primera conferencia se celebró en el año 1986.
Otros hechos que han influido considerablemente en el enorme desarrollo de los LPOO han sido la aparición de diferentes publicaciones periódicas exclusivamente dedicadas a orientación a objetos. En 1988 apareció la primera revista
de prestigio: The Journal of Object-Oriented Programming.
En la década de los noventa, los lenguajes, técnicas, interfaces gráficos y bases de datos se hicieron muy populares.
Sin duda, los noventa fué la década de la proliferación de tecnologías y lenguajes orientados a objetos. Microsoft, IBM,
Borland, Sun, AT &T, Digitalk, Symantec y otras grandes compañías lanzaron productos orientados a objetos de modo
continuo y progresivo.
Los lenguajes más implantados en la actualidad son Smalltalk y Eiffel, junto con C++, Object Pascal (Turbo/Borland
Pascal especialmente), Visual BASIC y Object Visual como lenguajes híbridos, y Java como un híbrido propio de Sun su fabricante- que reúne propiedades de C++, Ada-95, Object Pascal, Smalltalk, etc., diseñado para Internet con propiedades de objetos.
C++ es, sin lugar a dudas, el lenguaje más popular, aunque Smalltalk está ganando adeptos día a día. Tanto C++
como Smalltalk han sido implementados en diferentes plataformas: DOS, UNIX, OS/2, Windows e incluso en sistemas
grandes; su importancia reside en la gran cantidad de desarrolladores y vendedores que comercializan estos lenguajes.
Clasificación de lenguajes orientados a objetos
•
•
Como ya se ha comentado anteriormente, los lenguajes de programación orientados a objetos son: Eiffel, Lisp, Prolog,
Simula, Smalltalk, C++, Object Pascal, etc. Se entienden por lenguajes orientados a objetos aquellos que soportan las
características de orientación a objetos. Otros lenguajes de programación, tales como Ada, C, Clipper, pueden implementar algunas características orientadas a objetos, utilizando ciertas técnicas de programación, pero no se consideran orientados a objetos.
Los principales lenguajes de programación utilizados actualmente para sistemas de tiempo real son C y Ada. Ada fue
diseñado específicamente para la implementación de sistemas en tiempo real, especialmente empotrados. Aunque
Ada (Ada-83) no cumple las propiedades importantes de un LPOO (por ejemplo herencia y ligadura dinámica), soporta
un enfoque de diseño orientado a objetos y se le conoce usualmente como basado en objetos [Wegner, 87]. Ada-95,
ya estandarizado por ISO y ANSI, soporta herencia y ligadura dinámica; en consecuencia, aunque todavía con restricciones, se considera orientado a objetos.
Taxonomía de lenguajes orientados a objetos
•
Una taxonomía de lenguajes de programación con propiedades de orientación a objetos fue creada por Wegner. La
clasificación incluye los siguientes grupos:
Página 32
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
‰
Basado en objetos. Un lenguaje de programación es basado en objetos si su sintaxis y semántica soportan la
creación de objetos que tienen las propiedades descritas en temas anteriores.
‰
Basado en clases. Si un lenguaje de programación es basado en objetos y soporta además la creación de clases, se
considera basado en clases.
‰
Orientación a objetos. Un lenguaje de programación orientado a objetos es un lenguaje basado en clases que soporta también herencia.
Objetos
+ clases
Basado en objetos
Ada-83
Actor
Basado en clases
+ herencia
Clipper 5.x
Clu
Orientada a objetos
C++
Eiffel
Simula
Smalltalk
Turbo Borland Pascal
Delphi
Visual Object
Object COBOL
Ada-95
Figura 1.17. Taxonomía de lenguajes OO de Wegner
•
•
•
Esta taxonomía de orientación a objetos proporciona una definición estricta de los lenguajes de programación orientados a objetos, que ha prevalecido en la época actual. Según esta taxonomía, no es suficiente que un lenguaje soporte
la creación de objetos; para ser considerado orientado a objetos, es necesario que existan construcciones de creación
de clases y que soporten herencia adecuadamente.
C++ soporta la creación de objetos y clases, así como herencia, y es por consiguiente totalmente orientado a objetos.
Ada-83 soporta la creación de objetos mediante paquetes (tipos abstractos de datos). Un paquete en Ada no es una
definición de tipos como la clase C++, y en consecuencia Ada es un lenguaje basado en objetos. Ada-95 soporta,
además de las propiedades de Ada-83, clases y herencia, y se puede considerar orientado a objetos.
De acuerdo a la taxonomía de Wegner, se podría actualizar la clasificación de los lenguajes pensando en la segunda
década de los noventa:
‰
‰
‰
Lenguajes basados en objetos
Lenguajes basados en clases
Lenguajes orientados a objetos
Ada-83, Actor, Clipper 5.2, Visual Basic 4/5/6.
Clu.
C++, Objective-C, Java, Object Pascal, Delphi, Visual Object, Object COBOL,
Oyeron, Eiffel, Smalltalk, Simula, Prolog++, CLOS, Ada-95.
Características de los lenguajes orientados a objetos
•
Además de las características citadas anteriormente de objetos, clases y herencia, los LPOO deberán tener algunas, o
todas, las características que se citan a continuación:
Página 33
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
•
‰
Tipificación estricta (fuerte). Tipificación es el proceso de declarar el tipo de información que puede contener una variable. Los errores de programación relacionados con el número de parámetros, tipos de parámetros e interfaces de
módulos, se detectan durante las fases de diseño e implementación, en lugar de en tiempos de ejecución.
‰
Encapsulamiento. Es deseable que el lenguaje soporte ocultamiento de la información, mediante partes independientes, para la especificación y la implementación. Esta característica proporciona un diseño débilmente acoplado que
cumple con rigor el principio básico de la inferencia de software: acoplamiento débil y fuerte cohesión entre los
módulos de un programa.
‰
Compilación incremental. Característica en el desarrollo de sistemas grandes, en los que las porciones del sistema se
crean e implementan de un modo sistemático (poco a poco, etapa a etapa). Esta característica complementa la característica de tipificación estricta, que soporta partes independientes de implementación y específica.
‰
Genericidad. Las clases parametrizadas (mediante plantillas -templates- o unidades genéricas) sirven para soportar
un alto grado de reusabilidad (reutilización). Estos elementos genéricos se diseñan con parámetros formales, que se
instanciarán con parámetros reales, para crear instancias de módulos que se compilan y enlazan, y ejecutan posteriormente.
‰
Paso de mensajes. El lenguaje es conveniente que soporte paso bidimensional de mensajes entre módulos, lo que implicará módulos débilmente acoplados y diseños flexibles. Esto significa que se deben poder pasar señales entre
módulos, sin necesidad de tener que pasar realmente ningún dato.
‰
Polimorfismo. Los lenguajes deben permitir que existan operaciones con igual nombre, que se utilicen para manejar
objetos de tipos diferentes en tiempo de ejecución. El polimorfismo se implementa, normalmente, en unión con la
herencia.
‰
Excepciones. Se deben poder detectar, informar y manejar condiciones excepcionales utilizando construcciones del
lenguaje. Esta propiedad añadida al soporte de tolerancia a fallos del software permitirá una estrategia de diseño
eficiente.
‰
Concurrencia. Es conveniente que el lenguaje soporte la creación de procesos paralelos independientes del sistema
operativo. Esta propiedad simplificará la transportabilidad de un sistema de tiempo real de una plataforma a otra.
‰
Persistencia. Los objetos deben poder ser persistentes; es decir, los objetos han de poder permanecer después de la ejecución del programa.
‰
Datos compartidos. Los módulos se deben poder comunicar mediante memoria compartida, además del paso de mensajes.
Los lenguajes de programación disponibles actualmente no cumplen todas las características citadas anteriormente.
En general, los lenguajes orientados a objetos no soportan concurrencia; este es el caso de C++, aunque las versiones
de C++ que siguen el futuro estándar 4.0 comienzan a incorporar propiedades de concurrencia e incluso persistencia.
Asimismo, Ada-95, además de concurrencia, soporta ya herencia y polimorfismo.
Puros frente a híbridos
•
•
Existe un profundo debate entre los usuarios y desarrolladores de OO sobre la decisión del lenguaje a emplear. Este
debate no es reciente, aunque sí es en la actualidad cuando este debate se ha acrecentado y ha comenzado a ser decisivo en el desarrollo de la OO.
Un LPOO puro es un lenguaje diseñado para soportar únicamente el paradigma orientado a objetos, en el que todo
consta de objetos, métodos y clases. Los LPOO más populares son Smalltalk y Eiffel. Un LPOO híbrido, por otra parte,
soporta otros paradigmas de programación (tales como el tradicional -estructurado-, funcional, etc.), además del paradigma orientado a objetos. Los lenguajes híbridos se construyen a partir de otros lenguajes existentes, tales como C o
Pascal, de los cuales se derivan; es posible utilizar el LPOO de un modo no orientado a objetos y también como orientado a objetos utilizando objetos, clases y métodos.
Página 34
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
Lenguajes puros
Lenguajes híbridos
Objetos
Mensajes
Clases
Objetos
Mensajes
Clases
+
Lenguajes base tradicional
Figura 1.18. Lenguajes OO puros/híbridos
•
•
•
•
•
Cada tipo de lenguaje tiene sus ventajas e inconvenientes. Los lenguajes puros, tales como Smalltalk o Eiffel, pueden
ser más potentes, ya que utilizan todas las ventajas de la tecnología. Proporcionan su máxima flexibilidad para cambiar
los aspectos esenciales del lenguaje. Dado que todo en el lenguaje se construye sobre la base de los objetos, se pueden realizar cambios profundos si son necesarios.
Existe un precio, sin embargo, a la potencia y flexibilidad de los lenguajes puros. La mayoría de los lenguajes puros no
son tan rápidos como los híbridos y son difíciles de codificar en toda clase de operaciones fundamentales. Esto les
hace perder eficiencia en tiempo de ejecución.
En contraste, los lenguajes híbridos pierden con frecuencia alguna de las características de los lenguajes puros y
normalmente no permiten modificar características de construcción del lenguaje base; aunque, como ya se ha comentado, son normalmente más rápidos para operaciones construidas en el lenguaje base.
Los lenguajes puros e híbridos difieren también en la facilidad de aprendizaje, si bien esta facilidad dependerá del nivel
de cada persona. Así, para un programador la enseñanza de un lenguaje puro normalmente es más fácil, ya que es
más sencillo: sólo ha de aprenderse un lenguaje y no dos, como en el caso de un lenguaje híbrido. Sin embargo, para
un programador experimentado, el movimiento o emigración hacia un lenguaje híbrido puede ser más fácil si está ya
familiarizado con el lenguaje base, pues entonces sólo necesita dominar las extensiones orientadas a objetos.
En la actualidad, C++ es el lenguaje más popular y utilizado; sin embargo, Smalltalk está ganando día a día en aceptación, debido esencialmente a estar soportado por las plataformas DOS, UNIX y Windows. El hecho de que en 1994
IBM lanzase versiones de Smalltalk para sus sistemas OS/2 y AIX hizo crecer el número de usuarios de este lenguaje.
Por otra parte, Java se está configurando como un nuevo estándar para programación orientada a objetos.
Tipificación estática frente a dinámica
•
•
•
•
Tipificación o tipado (typing) es el proceso de declarar cuál es el tipo de información que puede contener una variable.
Por ejemplo, una variable se puede tipificar para contener un único carácter, una cadena de caracteres, un número entero o un número de punto flotante. Una vez que se ha declarado el tipo (tipificado), la variable está restringida a contener esa clase de datos. Cualquier intento de situar otra clase de datos en la variable producirá un mensaje de error.
Algunos lenguajes de objetos requieren que a todas las variables se les asigne un tipo antes de que se pueda utilizar.
Otros lenguajes no requieren esos requisitos, permitiendo que las variables puedan tomar sus tipos adecuados en
cualquier instante dado. Estas dos opciones se denominan tipificación fuerte, estricta o estática, y tipificación
débil, no estricta o dinámica.
La tipificación fuerte o sistemas de tipos estáticos exige que el programador asocie explícitamente un tipo con cada
nombre declarado en un programa, de modo que el compilador del lenguaje puede verificar que los nombres y expresiones compuestas de estos nombres se refieren siempre a los objetos del tipo especificado. El tipo de cada objeto se
ha de determinar y comprobar antes que se ejecute el programa. Lenguajes con sistemas de tipos estáticos son los
tradicionales FORTRAN, COBOL y PASCAL. La tipificación fuerte es menos flexible pero más segura, ya que el lenguaje puede realizar comprobaciones de rutinas para asegurar que los parámetros de los mensajes sean de tipo correcto.
Las ventajas de un lenguaje tipificado estáticamente son que los errores relativos a tipos se capturan (detectan) durante la compilación, antes de que se ejecute el programa, y el programa se puede ejecutar más eficientemente, dado que
Página 35
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
no hay necesidad de hacer ninguna verificación de tipos en tiempo de ejecución.
•
•
Los lenguajes con un sistema de tipos dinámicos (lenguajes de tipificación débil) no exigen que el programador especifique el tipo de objeto que puedan contener las variables cuando se escribe el programa. Cada objeto conoce su propio
tipo cuando se crea durante la ejecución. Las ventajas de los lenguajes con un sistema de tipos dinámicos son que los
programas son más flexibles y puede disponer de nuevos tipos de objetos que no fueron previstos cuando se escribió
el programa. Esta flexibilidad se hace a costa de una pérdida de eficiencia durante la ejecución del programa, debido a
la necesidad de mantener y comprobar el tipo de todos los objetos durante la ejecución.
Los lenguajes de objetos puros normalmente utilizan tipificación débil, ya que este enfoque les proporciona máxima
flexibilidad, especialmente durante el desarrollo, cuando se crean nuevos tipos objetos. Los lenguajes híbridos, en contraste, tienden a construirse como lenguajes fuertemente tipificados. Es posible especificar el tipo de un argumento, de
modo que haya flexibilidad en tiempo de ejecución, pero esta tarea requiere esfuerzos especiales.
*prueba = definir( int idPar )
Devuelve un apuntador
al objeto prueba
Método
definir
Requiere un parámetro
entero
Figura 1.19. Tipificación de un mensaje
Ligadura estática frente a dinámica
•
•
•
•
Ligadura es el proceso de asociar un atributo a un nombre. En el caso de funciones, el término ligadura (binding) se
refiere a la conexión o enlace entre una llamada a la función y el código real ejecutado como resultado de la llamada.
La ligadura se clasifica en dos categorías: ligadura estática y ligadura dinámica. La ligadura estática se conoce
también como ligadura temprana o anticipada y se realiza en tiempo de compilación. La ligadura dinámica se conoce
también como ligadura retardada o postergada y se realiza en tiempo de ejecución.
Normalmente, los lenguajes funcionales y orientados a objetos presentan ligadura dinámica, al contrario que los lenguajes imperativos, que suelen presentar ligadura estática. Desde el punto de vista de la estructura del lenguaje, los
intérpretes por definición realizan todos ligadura dinámica, mientras que los compiladores realizan normalmente ligadura estática.
Como ejemplo de ligadura estática, considere las declaraciones:
‰
‰
•
const n = 3;
var x : integer;
el valor 3 se enlaza estáticamente al nombre n, mientras que el tipo de dato integer se enlaza al nombre x. Por otra
parte, consideremos la sentencia de asignación x := 3; en este caso, se enlaza 3 dinámicamente a x cuando se ejecuta
la sentencia de asignación. Y la sentencia
new( y ) ;
enlaza dinámicamente una posición de almacenamiento a y y asigna a esa posición el valor de y.
Ejemplo de ligadura estática
•
Se desea procesar una determinada función, según sea un determinado carácter (código). Mediante una sentencia
switch se podría realizar el programa correspondiente en C++:
#include <ctype.h>
#include <iostream.h>
/ / .. .
static void salir( ), funcl( ) , func2( );
char car;
//;
Página 36
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
//car, contiene el código de carácter
int codigo = toupper( car );
switch ( codigo )
{
case ' S' : salir ( ) ;
case 'P' : funcl( );
break;
case '*' : func2( );
break;
default : cout << "Código desconocido: " << car << endl;
}
•
•
•
En este caso, la función invocada en respuesta a cada orden se conoce cuando el programa se está compilando, ya
que cada función se llama explícitamente por el nombre.
En el caso de propiedades orientadas a objetos, la ligadura se considera como el proceso mediante el cual se determina el receptor de un mensaje. En lenguajes que requieren ligadura estática, la identidad del receptor se debe especificar cuando se crea el programa. Si un lenguaje soporta ligadura dinámica, la identidad del receptor se puede dejar indeterminada hasta que se envía realmente el mensaje en tiempo de ejecución.
La ligadura dinámica permite la implementación de una de las características más sobresalientes de la orientación a
objetos: el polimorfismo.
Revisión de lenguajes orientados a objetos
•
•
•
•
•
•
Los dos lenguajes más utilizados en el desarrollo OO y más introducidos en el mercado son Eiffel, Smalltalk (en sus
versiones 80 y V), C++, Actor, Objective-C, CLOS, Object Pascal (especialmente Turbo Pascal) y Visual BASIC.
El lenguaje Ada se suele considerar por muchos autores como basado en objetos, debido esencialmente a que soporta
el concepto de abstracción de datos mediante el paquete y la genericidad mediante unidades genéricas; también es
considerado basado en objetos, debido a que Grady Booch, autor del famoso método de diseño Booch, se apoyó en
dicho lenguaje en su primera versión del método; la metodología HOOD también se apoya en Ada como lenguaje fundamental. La nueva versión Ada-95 ya es totalmente orientada a objetos.
El lenguaje Eiffel se examina brevemente, debido a que fue diseñado para soportar totalmente la orientación a objetos
y otras características de ingeniería de software. El uso de precondiciones, poscondiciones e invariantes mejoran significativamente la robustez y documentación de programas desarrollados en Eiffel.
Smalltalk, como heredero directo de Simula, es el prototipo de lenguaje de programación orientado a objetos puro.
Por la importancia del lenguaje C++ y dado que es el lenguaje utilizado en este curso para la implementación de los
conceptos orientados a objetos, se dedicarán capítulos específicos para enseñar la escritura y sintaxis del lenguaje, así
como reglas y consejos para mejorar el estilo de programación y reglas y consejos para la depuración de programas.
De cualquier forma, Meyer, creador del lenguaje Eiffel, proporciona unos criterios para considerar la bondad de un
lenguaje orientado a objetos, cuyos complementos configuran, de hecho, una nueva clasificación. En este sentido, los
criterios recogidos son los siguientes:
‰
‰
‰
‰
‰
‰
‰
•
La modularización de los sistemas ha de realizarse mediante estructuras de datos apropiadas.
Los objetos se describen como la implementación de tipos abstractos de datos.
La memoria se gestiona (administra) automáticamente.
Existe una correspondencia entre tipos de datos no elementales y clases.
Las clases se pueden definir como extensiones o restricciones de otras clases ya existentes mediante herencia.
Soportan polimorfismo y ligadura dinámica.
Existe herencia múltiple y repetida.
De acuerdo con los criterios de Meyer, recogemos en la Tabla 1 el cumplimiento de dichos criterios en los lenguajes
OO y basados en objetos más populares.
Página 37
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
Tabla 1. Criterios de Meyer en lenguajes OO y basados en objetos
Criterios
1. Modularización
2. Tipos abstractos de datos
3. Gestión automática de memoria
4. Sólo clases
5. Herencia
6. Polimorfismo (y ligadura
dinámica)
7. Herencia múltiple y repetida
Ada-83 Ada-95
C++
Eiffel Smalltalk Java
Sí
Sí
Sí
Sí
Sí
Sí
Sí
Sí
Sí
Sí
Sí
Sí
Sí
Sí
En parte
Sí
Sí
Sí
Sí
No
Sí
Sí
En parte
Sí
Sí
Sí
Sí
Sí
Sí
Sí
No
Sí
Sí
Sí
Sí
Sí
No
No
Sí
Sí
No
No
Página 38
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
1.3 Relación entre clases y objetos
•
Un objeto es un simple elemento, no importa lo complejo que pueda ser. Ciertamente, las cosas físicas son objetos. Un
balón, un archivero, una agenda, un árbol y una computadora son todos objetos. ¿Qué pasa con cosas como un número, una palabra, una cuenta bancaria o una nota musical? No son objetos físicos, pero son objetos porque tienen propiedades, o atributos, y podemos llevar a cabo acciones sobre ellos. Un número tiene un valor, y se pueden sumar dos
números. Una palabra tiene longitud y si estamos hablando de un procesador de textos, se puede borrar o insertar en
un documento. Una nota musical tiene tono, duración y volumen. Casi siempre, algo es un objeto si tiene:
‰
‰
‰
•
•
•
Cuando un objeto recibe un mensaje, se produce la ejecución de una acción o cambia una propiedad del objeto como
consecuencia de dicho mensaje. En el caso del control de un televisor, cuando el televisor recibe el mensaje “cambió de
canal” desde el control, cambia de canal.
Una clase, por el contrario, describe una familia de elementos similares. En la práctica, una clase es como un molde o
plantilla que se utiliza para definir o crear objetos.
A partir de una clase se puede definir un número determinado de objetos. Cada uno de estos objetos generalmente
tendrá un estado particular propio (una pluma estilográfica puede estar llena, otra puede estar medio llena y otra totalmente vacía) y otras características (como su color), aunque compartan algunas operaciones comunes ( como escribir
o llenar su depósito de tinta ). Los objetos tienen las siguientes características:
‰
‰
‰
‰
‰
‰
•
•
•
•
•
•
Se agrupan en tipos llamados clases.
Tienen datos internos que definen su estado actual.
Soportan ocultamiento de los datos.
Pueden heredar propiedades de otros objetos.
Pueden comunicarse con otros objetos pasando mensajes.
Tienen métodos que definen su comportamiento.
Una clase es un tipo definido que determina las estructuras de datos y operaciones asociadas con ese tipo. Las clases
son como plantillas que describen cómo están construidos ciertos tipos de objetos. Cada vez que se construye un objeto de una clase estamos creando lo que se llama una instancia (modelo o ejemplar) de una clase y la operación correspondiente se llama instanciación (creación de instancias). Por consiguiente, los objetos no som más que instancias
de clases. En general, los términos objeto e instancia de una clase se pueden utilizar indistintamente.
‰
‰
‰
•
Un nombre.
Propiedades asociadas al mismo.
Mensajes que puede entender.
Un objeto es una instancia de una clase.
Una clase puede tener muchas instancias y cada una es un objeto independiente.
Una clase es una plantilla que se utiliza para describir uno o más objetos de un mismo tipo.
La idea fundamental en los lenguajes orientados a objetos es combinar en una sola unidad datos y funciones que
operan sobre esos datos. Tal unidad se denomina objeto. Por consiguiente, dentro de los objetos residen los datos de
los lenguajes de programación tradicionales, tales como números, arreglos, cadenas y registros, así como funciones o
subrutinas que operan sobre ellos.
Las funciones dentro del objeto (funciones miembro en C++, métodos en Object Pascal, Java y C#) son el único medio
de acceder a los datos privados de un objeto. Si se desea leer un elemento datos de un objeto se llama a la función
miembro del objeto. Se lee el elemento y se devuelva el valor. No se puede acceder a los datos directamente. Los datos están ocultos, y eso asegura que no se pueden modificar accidentalmente por funciones externas al objeto.
Los datos y las funciones (procedimientos en Object Pascal) asociados se dicen que están encapsulados en una única
entidad o módulo. La encapsulación de datos y ocultamiento de datos son términos importantes en la descripción de
lenguajes orientados a objetos.
Si se desea modificar los datos de un objeto, se conoce exactamente cuáles son las funciones que interactúan con el
mismo. Ninguna otra función puede acceder a los datos. Esta característica simplifica la escritura, depuración y mantenimiento del programa.
Una clase es la descripción de un conjunto de objetos; consta de métodos y datos que resumen características comunes de un conjunto de objetos. Se puede definir muchos objetos de la misma clase. Dicho de otro modo, una clase es
la declaración de un tipo objeto.
Las clases son similares a los tipos de datos y equivalen a modelos o plantillas que describen cómo se construyen
ciertos tipos de objetos. Cada vez que se construye un objeto a partir de una clase estamos creando lo que se llama
Página 39
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
una instancia de esa clase. Una instancia es una variable de tipo objeto.
‰
•
•
•
•
•
•
•
•
•
En Poo un objeto es una instancia de una clase. Los objetos son miembros de una clase.
Cada vez que se construye un objeto de una clase se crea una instancia de esa clase. Los objetos se crean cuando un
mensaje de petición de creación se recibe por la clase.
Una clase es una colección de objetos similares.
Los objetos y las clases se comparan a variables y tipos en lenguajes de programación convencional. Una variable es
una instancia de un tipo, al igual que un objeto es una instancia de una clase; sin embargo, una clase es más expresiva que un tipo. Expresa la estructura y todos los procedimientos y funciones que se pueden aplicar a una de sus instancias.
En un lenguaje estructurado, un tipo int, por ejemplo, define la estructura de una variable entera, por ejemplo, una
secuencia de 16 bits y los procedimientos y funciones que se pueden realizar sobre enteros. De acuerdo a nuestra definición de clase, el tipo int será una clase. Sin embargo, en estos lenguajes de programación no es posible agrupar
nuevos tipos y sus correspondientes nuevas funciones y procedimientos en una única unidad. En un lenguaje orientado a objetos una clase proporciona este servicio.
La clase es la construcción del lenguaje utilizada más frecuentemente para definir los tipos abstractos de datos en
lenguajes de programación orientada a objetos.
Generalmente, una clase se puede definir como una descripción abstracta de un grupo de objetos, cada uno de los
cuales se diferencia por un estado específico y es capaz de realizar una serie de operaciones. Por ejemplo, una pluma
estilográfica es un objeto que tiene un estado (llena de tinta o vacía) que puede realizar algunas operaciones (por
ejemplo, escribir, poner/quitar la tapadera, rellenar si está vacía).
En programación, una clase es una estructura que contiene datos y procedimientos (o funciones) que son capaces de
operar sobre esos datos. Una clase pluma estilográfica puede tener, por ejemplo, una variable que indica si está llena
o vacía; otra variable puede contener la cantidad de tinta cargada realmente. La clase contendrá algunas funciones
que operan o utilizan esas variables. Dentro de un programa, las clases tienen dos propósitos principales: definir abstracciones y favorecer la modularidad.
¿Cuál es la diferencia entre una clase y un objeto, con independencia de su complejidad? Una clase verdaderamente
describe una familia de elementos similares. En realidad, una clase es una plantilla para un tipo particular de objetos.
Si se tienen muchos objetos del mismo tipo, solo se tienen que definir las características generales de ese tipo una
vez, en lugar de en cada objeto.
En resumen un objeto es una instancia de una clase.
Página 40
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
1.4 El papel de clases y objetos en el análisis y el diseño
•
•
Una de las tarea en el análisis y el diseño de sistemas es la identificación de las clases dentro del sistema. Primero,
revisamos el enunciado del problema y localizamos todos los sustantivos; con gran similitud, éstos representan a la
mayoría de las clases (o instancias de las clases) necesarias para la implementación del sistema. Normalmente estos
nombres o sustantivos y sus sinónimos se suelen escribir en una tabla de la que luego se deducirán los objetos reales.
Los objetos, según Shlaer, Mellor y Coad/Yourdon, pueden caer dentro de las siguientes categorías:
ƒ
ƒ
ƒ
ƒ
ƒ
ƒ
ƒ
•
•
•
•
•
•
•
Cosas tangibles: avión, reactor nuclear, fuente de alimentación, televisor, libro, automóvil, etc.
Roles o papeles jugados o representados por personas: gerente, cliente, empleado, médico, paciente, ingeniero.
Organizaciones: empresa, división, equipo, etc.
Incidentes que representan un suceso, evento u ocurrencia: vuelo, accidente, suceso, llamada a un servicio de
asistencia técnica, etc.
Interacciones que implican generalmente una transacción o contrato y que relacionan dos o más objetos del modelo: compras – comprador, vendedor – artículo, matrimonio – esposo – esposa – fecha de boda.
Especificaciones que muestran aplicaciones de inventario o fabricación: refrigerador, nevera, etc.
Lugares: sala de embarque, muelle de carga, etc.
Se modelan las clases del sistema y sus relaciones, mediante diagramas de clases.
Se modelan los objetos del sistema y sus vínculos. Los vínculos son relaciones sencillas entre los objetos, las asociaciones son a las clases como los vínculos son a los objetos.
Se identifican los atributos de las clases y se elabora un diagrama de estados. Los estados describen la condición de
un objeto (por ejemplo, los valores de los atributos de un objeto) en un determinado punto en el tiempo. Los diagramas
de estado nos brindan una forma de expresar cómo y bajo que condiciones el objeto de un sistema cambia de estado.
Se elabora el diagrama de actividad. El diagrama de actividad se centra en las acciones que realiza un objeto; en otras
palabras, el diagrama de actividad modela lo que hace un objeto durante su vida útil.
Se identifican las operaciones de una clase y con ella se elaboran los diagramas de secuencia. El diagrama de secuencia se enfoca en la manera en que se envían los mensajes entre los objetos en el tiempo.
Se elaboran los diagramas de colaboración. Una colaboración consiste en una colección de objetos que trabajan juntos
para llevar a cabo una tarea. Los diagramas de colaboración y los diagramas de secuencia proporcionan información
acerca de la manera en que interactúan los objetos, pero cada diagrama hace en información diferente. Los diagramas
de secuencia hacen énfasis en cuándo ocurren las interacciones. Los diagramas de colaboración hacen énfasis en
cuáles objetos participan en las interacciones y en las relaciones entre dichos objetos.
Dicho en pocas palabras, la participación de los objetos y las clases en la POO es de suma importancia.
DESARROLLO TRADICIONAL FRENTE A ORIENTADO A OBJETOS
•
•
•
•
•
El sistema tradicional del desarrollo del software para un determinado sistema es la subdivisión del mismo en módulos,
a la cual deben aplicarse criterios específicos de descomposición, los cuales se incluyen en metodologías de diseño.
Estos módulos se refieren a la fase de construcción de un programa, que en el modelo clásico sigue a la definición de
los requisitos (fase de análisis).
El modelo clásico del ciclo de vida del software no es el único modelo posible, dado que es posible desarrollar código
de un modo evolutivo, por refinamiento y prototipos sucesivos. Existen numerosos lenguajes de programación y metodologías que se han desarrollado en paralelo a los mismos, aunque normalmente con independencia de ellos.
Nos centraremos en la metodología más utilizada, denominada desarrollo estructurado, que se apoya esencialmente
en el diseño descendente y en la programación estructurada.
La programación estructurada es un estilo disciplinado de programación según los lenguajes procedimentales (por
procedimientos), tales como FORTRAN, BASIC, COBOL y recientemente C y C++.
Las metodologías del diseño descendente (o descomposición funcional) se centran en operaciones y tienden a descuidar la importancia de las estructuras de datos. Se basan en la célebre ecuación de Wirth:
Datos + Algoritmos = Programas
•
La idea clave del diseño descendente es romper un programa grande en tareas más pequeñas, más manejables. Si
una de estas tareas es demasiado grande, se divide en tareas más pequeñas. Se continúa con este proceso hasta que
Página 41
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
el programa se compartimentaliza en módulos más pequeños que se programan fácilmente. Los subprogramas facilitan el enfoque estructurado, y en el caso de lenguajes como C, estas unidades de programas, llamadas funciones, representan las citadas tareas o módulos individuales. Las técnicas de programación estructuradas reflejan, en esencia,
un modo de resolver un programa en términos de las acciones que realiza.
•
•
•
•
•
•
•
•
•
•
Para comprender mejor las relaciones entre los algoritmos (funciones) y los datos, consideremos una comparación con
el lenguaje natural (por ejemplo, español o inglés), que se compone de muchos elementos, pero que reflejará poca expresividad si sólo se utilizan nombres y verbos. Una metodología que se basa sólo en datos o sólo en procedimientos
es similar a un lenguaje en el que sólo se utilizan nombres o verbos. Sólo enlazando nombres o verbos correctos (siguiendo las reglas semánticas), las expresiones tomarán formas inteligibles y su proceso será más fácil.
Las metodologías tradicionales se vuelven poco prácticas cuando han de aplicarse a proyectos de gran tamaño. El
diseño orientado a objetos se apoya en lenguajes orientados a objetos que se sustentan, fundamentalmente, en los tipos de datos y operaciones que se pueden realizar sobre los tipos de datos. Los datos no fluyen abiertamente en un
sistema, como ocurre en las técnicas estructuradas, sino que están protegidos de modificaciones accidentales. En programación orientada a objetos, los mensajes (en vez de los datos) se mueven por el sistema. En lugar del enfoque
funcional (invocar una función con unos datos), en un lenguaje orientado a objetos, se envía un mensaje a un objeto.
De acuerdo con Meyer, el diseño orientado a objetos es el método que conduce a arquitecturas de software basadas
en objetos que cada sistema o subsistema evalúa.
Recordemos ¿qué son los objetos? Un objeto es una entidad cuyo comportamiento se caracteriza por las acciones
que realiza. Con más precisión, un objeto se define como una entidad caracterizada por un estado; su comportamiento
se define por las operaciones que puede realizar; es una instancia de una clase; se identifica por un nombre; tiene una
visibilidad limitada para otros objetos; se define el objeto mediante su especificación y su implementación.
Una definición muy elaborada se debe a Meyer: «Diseño orientado a objetos es la construcción de sistemas de software como colecciones estructuradas de implementaciones de tipos de datos abstractos.»
La construcción de un sistema se suele realizar mediante el ensamblado ascendente (abajo-arriba) de clases ya existentes. Las clases de un sistema pueden tener entre sí, como se verá en los siguientes temas, relaciones de uso (cliente), relaciones de derivación (herencia) o relaciones de agregación (composición) o incluso sólo relaciones de asociación. Así, por ejemplo, con una relación de cliente, una clase puede utilizar los objetos de otra clase; con una relación
de herencia, una clase puede heredar o derivar sus propiedades definidas en otra clase.
El hardware se ensambla a partir de componentes electrónicos, tales como circuitos integrados (chips), que se pueden
utilizar repetidamente para diseñar y construir conjuntos mucho más grandes, que son totalmente reutilizables. La calidad de cada nivel de diseño se asegura mediante componentes del sistema que han sido probados previamente a su
utilización. El ensamblado de componentes electrónicos se garantiza mediante interfaces adecuados.
Estos conceptos se aplican también con tecnologías de objetos. Las clases (tipos de objetos) son como los chips de
hardware, Cox les llamó chips de software, que no sólo se pueden enlazar (ensamblar) entre sí, sino que también se
pueden reutilizar (volver a utilizar). Las clases se agruparán normalmente en bibliotecas de clases, que son componentes reutilizables, fácilmente legibles.
En la actualidad existe gran cantidad de software convencional, en su mayoría escrito normalmente para resolver
problemas específicos; por esta razón, a veces es más fácil escribir nuevos sistemas que convertir los existentes.
Los objetos, al reflejar entidades del mundo real, permiten desarrollar aplicaciones, creando nuevas clases y ensamblándolas con otras ya existentes. Normalmente, los desarrolladores experimentados gastan un porcentaje alto de
su tiempo (20 al 40%) en crear nuevas clases y el tiempo restante en ensamblar componentes probados de sistemas,
construyendo sistemas potentes y fiables.
Beneficios de las Tecnologías de objetos (TO)
•
Una pregunta que hoy día se hacen muchos informáticos es: ¿ Cuál es la razón para introducir métodos de TO en los
procesos de desarrollo? La principal razón, sin lugar a dudas, son los beneficios de dichas TO: aumento de la fiabilidad
y productividad del desarrollador. La fiabilidad se puede mejorar, debido a que cada objeto es simplemente «una caja
negra» con respecto a objetos externos con los que debe comunicarse. Las estructuras de datos internos y métodos se
pueden refinar sin afectar a otras partes de un sistema (Figura 1.20).
Página 42
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
Objeto
Métodos
Datos
Figura 1.20. El objeto como caja negra
•
•
Los sistemas tradicionales, por otra parte, presentan con frecuencia efectos laterales no deseados. Las tecnologías de
objetos ayudan a los desarrolladores a tratar la complejidad en el desarrollo del sistema.
La productividad del desarrollador se puede mejorar, debido a que las clases de objetos se pueden hacer reutilizables
de modo que cada subclase o instancia de un objeto puede utilizar el mismo código de programa para la clase. Por
otra parte, esta productividad también aumenta, debido a que existe una asociación más natural entre objetos del sistema y objetos del mundo real.
Figura 1.21. Proceso tradicional de datos
•
Taylor considera que los beneficios del modelado y desarrollo de objetos son:
‰
‰
‰
‰
‰
‰
‰
•
Sin embargo, Taylor también considera algunos inconvenientes, aunque algunos de ellos ya han sido superados o al
menos reducido su impacto.
‰
‰
‰
‰
‰
‰
‰
•
Desarrollo más rápido.
Calidad más alta.
Mantenimiento más fácil.
Costo reducido.
Incremento en escalabilidad.
Mejores estructuras de información.
Incremento de adaptabilidad.
Inmadurez de la tecnología (hoy día ya no se puede considerar así).
Necesidades de estándares ( el grupo OMG es una realidad).
Necesidad de mejores herramientas.
Velocidad de ejecución.
Disponibilidad de personal calificado.
Costo de conversión.
Soporte para modularidad a gran escala.
A continuación se muestran los beneficios genéricos de las tecnologías de objetos.
‰
‰
‰
‰
‰
‰
‰
Reutilización. Las clases se construyen a partir de otras clases.
Sistemas más fiables.
Proceso de desarrollo más rápido.
Desarrollo más flexible.
Modelos que reflejan mejor la realidad.
Mejor independencia e interoperatividad de la tecnología.
Mejor informática distribuida y cliente-servidor.
Página 43
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
‰
‰
‰
Bibliotecas de clases comerciales disponibles.
Mejores relaciones con los clientes.
Mejora la calidad del producto software terminado.
DISEÑO ORIENTADO A OBJETOS
•
•
•
•
•
•
•
•
Para sustentar los principios descritos anteriormente, se han desarrollado distintas metodologías de diseño y programación. Recientemente, un enfoque: el diseño y la programación orientada a objetos, se ha mostrado particularmente prometedor para ayudar a los desarrolladores de software a lograr los objetivos de fiabilidad, rendimiento, adaptabilidad, comprensibilidad y reutilidad.
El diseño de software orientado a objetos elabora el software como un modelo muy próximo a la forma en que
pensamos e interactuamos en el mundo real. A temprana edad, aprendemos acerca de los objetos y de cómo se manipulan. Los bebés, por ejemplo, aprenden que si mueven un sonajero hará ruido. A medida que desarrollan sus capacidades cognoscitivas, son conscientes de que los objetos tienen propiedades y empiezan a pensar en ellos de forma
abstracta. El bebé pronto se dará cuenta de que hacer ruido es una capacidad de todos los sonajeros.
Para ilustrar como la visión del mundo, como un conjunto de objetos, facilita el manejo de su complejidad, consideremos una actividad que muchos de nosotros hacemos: ver la televisión. Mirando la televisión recuerda que su programa
favorito empezará pronto en un canal distinto. Toma el control, oprime el botón y cambia al canal deseado.
Analicemos esta actividad. Primero, tomó el control, que es un objeto físico. Dicho objeto tiene propiedades, tales
como peso y tamaño, y además puede hacer algo: enviar mensajes a la televisión. No está claro de cómo lo hace o
cómo están codificados los mensajes, pero no es necesario saberlo. Sólo necesita saber cómo se oprimen los botones
adecuados. Los botones son la interfaz del control. Si se conoce la interfaz de un objeto, se puede usar dicho objeto
para hacer algo, aunque no se sepa cómo funciona. Cuando oprimió los botones adecuados hizo que el control enviase algunos mensajes al televisor. El televisor es también un objeto físico con varias propiedades. Al recibir el mensaje
del control, el televisor cambió al canal deseado.
Estas interacciones son tan rutinarias que es fácil no darse cuenta de lo sorprendente de esta actividad. Ha sido capaz
de hacer que dos objetos interaccionen y ejecuten una actividad compleja sin comprender el funcionamiento interno de
ninguno de ellos. Fue capaz de hacerlo así porque disponía de las abstracciones apropiadas para ambos objetos.
Además, su abstracción mental del control implica que puede ir a casa de un amigo y ser capaz de usar su control y su
televisor, incluso aunque tengan una marca de televisor distinta. Objetos similares muestran un comportamiento similar.
Esta forma de afrontar nuestro mundo puede ser aplicada al diseño y a la programación de software. Un paso clave en
el desarrollo de un sistema complejo usando diseño orientado a objetos es determinar los objetos que constituyen el
sistema. Creando cuidadosamente abstracciones de estos objetos y separando su implementación interna de su
comportamiento externo, se puede manejar la complejidad de un sistema de software de gran tamaño.
Si vamos a adoptar un enfoque orientado a objetos para desarrollar software, tiene sentido usar un lenguaje de programación que sustente esta forma de pensar y permita implementar soluciones en términos de objetos. Un lenguaje
que tiene esas características es un lenguaje de programación orientada a objetos. Observe que se ha tenido cuidado
de incluir la frase implementar un diseño orientado a objetos. Ya que se puede usar un lenguaje orientado a objetos,
pero no pensar en términos de objetos.
Algunos lenguajes orientados a objetos populares actualmente son Smalltalk y C++. Las características que incluyen
para manejar objetos son, en su mayor parte, idénticas. Difieren principalmente en la terminología usada para referirse
a los objetos y en la sintaxis del lenguaje.
Página 44
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
RESUMEN
‰
La orientación a objetos es una manera natural de pensar acerca del mundo y de escribir programas de
computadora.
‰
Los objetos tienen atributos (como tamaño, forma, color, peso y aspecto) y exhiben un comportamiento.
‰
Los humanos aprendemos acerca de los objetos mediante el estudio de sus atributos y la observación de
su comportamiento.
‰
Objetos distintos pueden tener muchos atributos iguales y exhibir un comportamiento similar.
‰
La programación orientada a objetos (POO) modela objetos del mundo real con contrapartes en software.
Toma ventaja de las relaciones entre clases, en donde los objetos de cierta clase tiene las mismas características y comportamientos. Aprovecha las relaciones de herencia e incluso las relaciones de herencia
múltiple, en donde las clases recién creadas se derivan mediante la herencia de las características de clases existentes, aunque contiene características únicas propias.
‰
La programación orientada a objetos proporciona una manera intuitiva de ver el proceso de programación, a saber, mediante el modelado de objetos reales, sus atributos y sus comportamientos.
‰
La POO también modela la comunicación entre objetos mediante mensajes.
‰
La POO encapsula los datos (atributos) y las funciones (comportamiento) dentro de los objetos.
‰
Los objetos tienen la propiedad de ocultar información. Aunque los objetos pueden saber como comunicarse entre sí a través de interfaces bien definidas, los objetos por lo general no están autorizados para saber los detalles de la implementación de otros objetos (para eliminar dependencias innecesarias).
‰
El ocultamiento de información es crucial para una buena ingeniería de software.
‰
En C y en otros lenguajes de programación por procedimientos, la programación tiende a ser orientada a
acciones. En realidad, los datos son importantes en C, pero la visión es que los datos existen primordialmente para permitir las acciones que realizan las funciones.
‰
Los programadores en C++ se concentran en la creación de sus propios tipos definidos denominados
clases. Cada clase contiene datos, así como el conjunto de funciones que manipulan los datos. Los componentes de datos de una clase se denominan datos miembro. Los componentes de función de una clase
se denominan funciones miembro o métodos.
Página 45
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
EJERCICIOS
1)
Llene el espacio vacío con el término de objetos correcto de cada una de las siguientes oraciones:
a)
b)
c)
d)
e)
f)
g)
h)
i)
j)
2)
Los humanos podemos ver hacia la pantalla del televisor y ver puntos de colores, o podemos retroceder y ver a tres
personas sentadas en una mesa de conferencias, éste es un ejemplo de una capacidad llamada
__________________.
Si vemos un automóvil como un objeto, el hecho de que sea convertible es un atributo/comportamiento (elija uno)
_________________ del automóvil
El hecho de que un automóvil pueda acelerar o desacelerar, dar vuelta a la izquierda o a la derecha, o ir hacia delante y hacia atrás es un ejemplo de _____________ del automóvil.
Cuando una nueva clase hereda las características de distintas clases diferentes, a esto se le denomina herencia
_____________________.
Los objetos se comunican entre sí enviándose ____________________.
Los objetos se comunican entre sí mediante el uso de __________________ bien definidas.
Por lo general, a un objeto no se le permite saber cómo están implementados otros objetos; a esta propiedad se le llama ______________________.
Los _______________ en una especificación de sistema ayuda al programador de C++ a determinar las clases que
se requerirán para implementar el sistema.
Los componentes de datos de una clase se llaman ____________ y a los componentes de función de una clase se
les llama _________________________.
A una instancia de un tipo definido por el usuario se le llama _________________.
Responda de manera breve cada una de las siguientes preguntas pensando en objetos:
a)
b)
c)
d)
e)
¿Por qué se prefiere explicar primero y con detalle la programación estructurada, antes de explicar a fondo la programación orientada a objetos?
¿Cuáles son los pasos típicos de un proceso de diseño orientado a objetos?
¿Cómo se puede mostrar la herencia múltiple en los seres humanos?
¿Qué tipo de mensajes se envía la gente entre sí?
Los objetos se envían mensajes entre sí a través de interfaces bien definidas. ¿Qué tipos de interfaces presenta el radio de un automóvil (objeto) a su usuario (objeto persona)?
3)
Probablemente porta en su muñeca uno de los objetos más comunes en el mundo, un reloj. Explique cómo cada uno
de los siguientes términos y conceptos se pueden aplicar a la noción de un reloj: objeto, atributo, comportamiento, clase, herencia (por ejemplo, considere un reloj de alarma), abstracción, modelado, mensajes, encapsulado, interfaz, información, ocultamiento, datos miembro y funciones miembro.
4)
Considere un cajero automático en un banco. ¿Cuáles son algunas de las propiedades relevantes del cajero para las
siguientes persona?
a)
b)
c)
d)
Un usuario.
Una persona de mantenimiento.
Un empleado del banco.
El presidente del banco.
5)
Dé un ejemplo de encapsulamiento en el funcionamiento de un contestador automático telefónico.
6)
La mayor parte de los sistemas son modulares. Nombre algunos de los componentes/módulos de los siguientes sistemas:
a)
b)
c)
d)
e)
7)
Equipo de música.
Televisor.
Lavadora.
Video.
Bicicleta.
La mayoría de las organizaciones tienen una estructura jerárquica. Elija una organización a la que pertenezca y dibuje
un diagrama que ilustre su jerarquía.
Página 46
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
8)
¿Son los siguientes elementos objetos? Justifique su respuesta.
a)
b)
c)
d)
e)
9)
Belleza.
Tiempo.
Celos.
Arbol.
Bosque.
Casi todos los dispositivos electrónicos han sido diseñados siguiendo el principio de modularidad, que hace que los
dispositivos sean más fáciles de fabricar y reparar. Nombre los principales componentes de los siguientes dispositivos:
a)
b)
c)
d)
e)
f)
Televisor.
Video.
Horno de microondas.
Equipo de música.
Radio.
Teléfono.
10) ¿Por qué se presta tanta atención hoy día a la programación orientada a objetos en general y a C++ en particular?
Página 47
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
EJEMPLO DE DISEÑO ORIENTADA A OBJETOS
•
Para mostrar algunas características de un lenguaje orientado a objetos, se va a hacer un esbozo de diseño de un
sencillo juego de computadora llamado CAZA DE LA PULGA. El propósito de este juego, más que nada es ayudar a
la gente a desarrollar su coordinación cuando usa un ratón de computadora. El juego funciona de la manera siguiente:
‰
El juego CAZA DE LA PULGA está formado por una ventana con la imagen de una pulga. La pulga
cambia de direcciones aleatoriamente dentro de la ventana (ver figura 1.22).
‰
El objetivo del juego es eliminar a la pulga. Una pulga es eliminada aplastándola, es decir oprimiendo el
botón del ratón cuando la pulga está debajo. Son pulgas duras y hay que aplastarlas varias veces hasta
matarlas.
‰
Hay dos tipos de pulgas: lentas y rápidas. Obviamente, una pulga lenta se mueve más despacio que una
rápida. Cuando se elimina la primera pulga, una más rápida toma su lugar.
‰
Si se falla (es decir, se oprime el botón del ratón cuando la pulga no está debajo), el jugador pierde. Un
jugador gana cuando elimina las pulgas lentas y rápidas sin fallar.
‰
Los dos tipos de pulgas se mueven de forma distinta. Cuando una pulga lenta llega al borde de la ventana, cambia de dirección como si hubiera chocado con una pared.
‰
Cuando una pulga rápida alcanza el borde de la ventana, la atraviesa y aparece por el lado opuesto de
la ventana.
Caza de la Pulga
Movimientos posibles de la pulga
PULGA
Dirección actual
Figura 1.22. El juego Caza de la pulga
•
Los pasos sugeridos en el diseño orientado a objetos son los siguientes:
Paso 1. Determinar los objetos que se definen en el problema.
Paso 2. Para cada objeto determinar sus atributos (propiedades) y sus acciones.
•
•
•
De la definición del problema, se pueden extraer algunos objetos identificando los nombres. Los objetos nombrados en
la definición del problema son: ventana, ratón y pulga.
Para mostrar las características disponibles en un lenguaje orientado a objetos, nos centraremos en el diseño de los
dos objetos pulga. El diseño de los objetos ventana y ratón son similares.
Para cada pulga, es necesario determinar las propiedades asociadas con ella y las acciones que pueden realizar.
Según el problema, una pulga tiene las siguientes propiedades o atributos:
Página 48
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
‰
‰
‰
‰
‰
•
Una pulga debe ser capaz de manejar los siguientes mensajes o mandatos:
‰
‰
‰
‰
‰
‰
•
•
•
•
•
Una Posición en la ventana.
Una imagen.
Velocidad.
Dirección.
Resistencia (es decir, el número de golpes necesarios para eliminar la pulga).
Dibujar.
Mover (es decir, actualizar su posición).
Cambiar la dirección en que se mueve.
Golpear (es decir, decir a la pulga que ha sido aplastada).
Matar (decir a la pulga que debe morir).
estaApuntandoA (pregunta a la pulga si el cursor del ratón está sobre ella).
Estas propiedades y mensajes forman la abstracción de las pulgas del juego.
Los lenguajes orientados a objetos proporcionan una forma de definir una abstracción mediante la encapsulación de
sus propiedades y mensajes en un único concepto, denominado clase.
Cuando un conjunto de propiedades y mensajes están encapsulados en una clase, se dice que son miembros de la
clase. Los miembros que definen las propiedades de una clase se denominan miembros de datos, porque contienen
información. Los mensajes que una clase puede manejar se denominan métodos o miembros de función.
La diferencia entre clase y objeto es sutil, pero importante. Mientras una clase es un concepto abstracto, un objeto es
una entidad concreta. Por ejemplo, el concepto de automóvil es una clase, pero un Ford Taunus con interior de piel y
motor V-6 es un objeto. En términos prácticos, se puede pensar en una clase como una plantilla para un objeto. A partir de la clase, se pueden crear o instanciar objetos con propiedades específicas.
La noción de instanciar un objeto concreto a partir de una clase abstracta se muestra en la figura 1.23. En ella se
instancian tres pulgas distintas, cada una con su propia posición, imagen, velocidad, dirección y resistencia, a partir de
la clase pulga. En esencia, una clase define las propiedades y mensajes de un objeto. La instanciación crea un objeto con valores específicos para cada una de las propiedades.
Página 49
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
PULGA
MENSAJES
PROPIEDADES
Posición
Imagen
Velocidad
Dirección
Resistencia
Dibujar
Mover
FijarDireccion
Golpear
Matar
estarApuntandoA
La clase
pulga
Objetos pulga
con propiedades
particulares
Posición: 1, 2
Imagen
Velocidad: 3
Dirección: arriba
Resistencia: 3
Dibujar
Mover
FijarDireccion
Golpear
Matar
estarApuntandoA
Pulga
Posición: 12, 2.2
Imagen
Velocidad: 4
Dirección: izquierda
Resistencia: 4
Dibujar
Mover
FijarDireccion
Golpear
Matar
estarApuntandoA
Pulga
Pulga
Posición: 5, 3.8
Imagen
Velocidad: 2
Dirección: derecha
Resistencia: 2
Dibujar
Mover
FijarDireccion
Golpear
Matar
estarApuntandoA
Figura 1.23. Instanciación de tres objetos pulga a partir de la clase pulga
•
Se puede pensar en crear una clase por cada tipo de pulga (lenta y rápida) e instanciar tipos distintos de pulga según
se requiriera. Sin embargo, una característica importante de los lenguajes orientados a objetos es que permiten al programador explotar la similitud de los objetos. Si piensa acerca de ello, una pulga rápida y una pulga lenta tienen muchas características en común. Tanto si una pulga es rápida como si es lenta, tiene posición, imagen, velocidad, dirección y resistencia. De hecho, la única característica que distingue a ambas pulgas es cómo se mueven. Una pulga lenta da la vuelta cuando llega al borde de la ventana, mientras que una rápida la atraviesa y reaparece por el borde
opuesto de la ventana. Por lo tanto, se puede pensar en crear una pulga básica que capture los atributos y comportamientos que todas las pulgas tienen en común y usarla para crear dos tipos esenciales de pulgas, pulgaLenta y pulgaRapida, que se comportan de forma distinta cuando llegan al borde de la ventana. Así, ambas pulgas son tipos especiales de pulga. Estas relaciones, definen una jerarquía como se muestra en la figura 1.24.
Página 50
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
Pulga
PROPIEDADES
MENSAJES
Posición
Dibujar
Imagen
Mover
Velocidad
FijarDireccion
Dirección
Golpear
Resistencia
Matar
EstarApuntandoA
Es una
Es una
PulgaRapida
PulgaLenta
Propiedades
Mensajes
Propiedades
Mover
Mensajes
Mover
Mensaje específico de pulgaLenta
Mensaje específico de pulgaRapida
Figura 1.24. Abstracción y herencia de pulgas con diferente comportamiento
•
•
•
•
En la parte alta del diagrama está la clase Pulga. Esta clase, la más general, se denomina a veces clase base o
superclase.
Debajo de la clase base están las subclases o clases derivadas. Las clases derivadas heredan mensajes y propiedades de sus ancestros.
Por lo tanto la PulgaRapida y la PulgaLenta tienen como propiedades su posición, Imagen, Velocidad, Dirección y
Resistencia. De forma similar, una PulgaRapida y una PulgaLenta entienden los siguientes mensajes o mandatos: Dibujar, Mover, FijarDireccion, Golpear, Matar y EstarApuntandoA. La noción de herencia es una característica que define a los lenguajes orientados a objetos.
La habilidad de una clase para heredar propiedades y funciones miembro de un ancestro sustenta el principio de reutilización. Ambos tipos de pulgas comparten las funciones miembro para Dibujar, Mover, FijarDireccion, Golpear, Matar
y EstaApuntandoA. Estas funciones sólo se implementan una vez.
Página 51
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
•
•
•
•
•
•
•
La jerarquía para la clase Pulga ilustra otra característica de los lenguajes orientados a objetos: el polimorfismo. El
polimorfismo es la capacidad de asumir diferentes formas. En un lenguaje orientado a objeto, el polimorfismo es la
propiedad que permite que un mensaje pueda significar distintas cosas dependiendo del objeto que lo reciba.
El mensaje Mover significa una cosa distinta si se envía a un objeto PulgaLenta o a una de tipo PulgaRapida. Una
pulga lenta da la vuelta cuando llega al borde de la ventana, mientras que una pulga rápida hace un túnel hasta el otro
lado. Este uso del polimorfismo se ilustra en la figura 1.18 mediante la inclusión del mensaje Mover para los objetos:
PulgaLenta y PulgaRapida.
El polimorfismo es un concepto natural que se aplica bien a los objetos. Objetos similares aceptan a menudo los mismos mensajes, pero hacen cosas distintas. Por ejemplo, considere la interfaz gráfica de una computadora. Los objetos
son iconos que representan archivos. Se usa el ratón para enviar mensajes a estos objetos. Un mensaje típico es una
doble pulsación, que se envía al objeto colocando el ratón sobre su icono y pulsando el ratón dos veces. Para un archivo ejecutable, ese mensaje significa que debe ejecutar el archivo, mientras que para un archivo de texto, la pulsación doble indica que debe arrancar el editor de texto y abrir el archivo para editarlo.
El desarrollo de la jerarquía de Pulga ilustra mucha de las características disponibles en un lenguaje orientado a objetos. Sin embargo, para demostrar completamente la potencia del diseño y la programación orientada a objetos, es necesario discutir cómo se puede crear un sistema completo a partir de un conjunto de objetos. Se hará mediante el diseño esquemático de alto nivel del juego CAZA DE LA PULGA.
Recuerde que, de la descripción previa que se hizo del juego, los otros objetos mencionados fueron el ratón y la ventana. Ciertamente, es necesario desarrollar estos objetos. Sin embargo, en la descripción se menciona otro objeto muy
importante: ¡el mismo juego! Es fácil de olvidar, porque la definición del problema es una descripción de este objeto. Si
lo piensa un momento, tiene sentido pensar en el juego como en un objeto. Desde un punto de vista abstracto, el objeto juego es el elemento que coordina las actividades de otros objetos y asegura el cumplimiento de las reglas del juego. Se llamará a este objeto, que es el juego, ControladorDeJuego.
Ahora ya se puede completar el diseño de alto nivel del juego. Como se mencionó, se necesitan los objetos ventana y
ratón. Por ahora, se ignorará el objeto ventana. Aunque es necesaria para la realización del juego, la creación y el control de la ventana no tienen un papel fundamental en la operación del juego. El ratón, por otro lado, es un componente
fundamental del juego, ya que gran parte de la acción del juego se centra en las actividades del ratón. La visión abstracta del ratón, Raton, es la de un objeto que envía mensajes al ControladorDeJuego. El raton envía un mensaje al
ControladorDeJuego cada vez que se pulsa un botón. El mensaje contiene la posición en la pantalla del cursor.
Con las abstracciones Raton y Pulga, el diseño y manejo del juego es bastante sencillo. El manejo global se ilustra en
la figura 1.25. Cuando se pulsa una tecla del ratón, el Ratón envía el mensaje PulsacionRaton al ControladorDeJuego. Este extrae la posición del ratón del mensaje y envía un mensaje EstaApuntandoA, que incluye la posición del
ratón, a la pulga de la pantalla. La pulga determina si la posición en el mensaje está dentro de ella. Si el ratón apunta
a la pulga, responde sí al mensaje; en caso contrario, responde no. Si el ControladorDeJuego recibe una respuesta
afirmativa, envía un mensaje de La pulga fue golpeada. Si se ha sobrepasado la resistencia de la pulga, la pulga responde al mensaje diciendo que no tiene más resistencia. Si se recibe esta respuesta, el ControladorDeJuego mata a
la pulga. Si la pulga era lenta, el controlador crea una PulgaRapida y el juego continúa. Las interacciones entre el
ControladorDeJuego y la Pulga se muestran en la figura 1.25.
Caza de la pulga
controladorDeJuego
Respuesta: si o no
pulga
¿estaApuntandoA?
PulsacionRaton
pulsacionRaton
raton
Figura 1.25. Interacción entre el controlador del juego, el ratón y la pulga.
Página 52
Ing. Isis Espinosa Salazar
Fundamentos de Programación Orientada a Objetos
•
Si la pulga responde que no, el ratón no está apuntando sobre ella; en ese caso, el ControladorDeJuego crea una
nueva ventana y muestra un mensaje diciendo al jugador que ha perdido el juego. Si se ha eliminado a todas las pulgas sin errores, el controlador muestra un mensaje felicitando al jugador por su habilidad con el ratón. Por supuesto,
quedan muchos detalles que perfilar para completar la implementación del juego. Sin embargo, el diseño de alto nivel
está resuelto.
EJERCICIOS
1.
Esboce el diseño de la clase Ventana para el juego CAZA DE LA PULGA. Asegúrese de incluir los
atributos (es decir, miembros de datos) y las acciones (es decir, miembros de función) que la clase debe
tener.
2.
Esboce el diseño de la clase Ratón para el juego CAZA DE LA PULGA. Asegúrese de incluir los atributos (es decir, miembros de datos) y las acciones (es decir, miembros de función) que la clase debe tener.
3.
Esboce el diseño de la clase ControladorDeJuego para el juego CAZA DE LA PULGA. Asegúrese de
incluir los atributos (es decir, miembros de datos) y las acciones (es decir, miembros de función) que la
clase debe tener.
4.
Usando los diseños de los problemas 1 y 3, dibuje un diagrama que muestre cómo podrían interactuar las
distintas clases entre sí.
5.
Esboce un diseño orientado a objetos de una máquina despachadora de refrescos. ¿Cuáles son los objetos
clave? ¿Cuáles son los atributos y comportamientos de los objetos? ¿Cómo interaccionan los objetos?
6.
El ejemplo herencia en la figura 1.24 ignora algunos detalles. Considere los siguientes temas:
a) La posición es una propiedad de todas las pulgas. ¿Cómo se podría especificar la posición?
b) Trace las acciones que una pulga ejecuta cuando recibe un mensaje Matar.
7.
Extienda la jerarquía de la clase de la figura 1.24 para incluir una clase PulgaEspectro. Una PulgaEspectro desaparece ocasionalmente y reaparece en una nueva posición. ¿Es necesario cambiar las propiedades
de Pulga?
Página 53
Ing. Isis Espinosa Salazar
Descargar