next up previous
Siguiente: 5 Más Conceptos de Orientación a Objetos Arriba: Introducción a la Programación Orientada a Objetos Anterior: 3 Tipos de Datos Abstractos

Subsecciones

4 Conceptos de Orientación a Objetos

 
Peter Müller
Globewide Network Academy (GNA)
pmueller@uu-gna.mit.edu

Las secciones anteriores introducen ya algunos conceptos "de orientación a objetos". Sin embargo, éstos fueron aplicados en un ambiente procedimental o de una manera verbal. En esta sección investigamos estos conceptos en más detalle y les damos nombres tal y como se usan en los lenguajes de programación orientada a objetos existentes.

4.1 Implementación de Tipos de Datos Abstractos

La última sección introduce los tipos de datos abstractos (TDAs) como una perspectiva abstracta para definir propiedades de un conjunto de entidades. Los lenguajes de programación orientada a objetos deben permitir la implementación de estos tipos. Consecuentemente, una vez que un TDA se ha implementado, tenemos disponible una representación particular de éste.

Considera nuevamente el TDA Integer. Lenguajes de programación tales como Pascal, C, Modula-2 y otros, ofrecen ya una implementación de dicho tipo. Algunas veces se le llama int o integer. Una vez que has creado una variable de este tipo, ya puedes usar sus operaciones provistas. Por ejemplo, tú puedes sumar dos integers :

  int i, j, k;    /* Define tres integers */

  i = 1;          /* Asigna 1 al  integer i */
  j = 2;          /* Asigna 2 al integer j */
  k = i + j;      /* Asigna la suma de (i) y (j) a (k) */

Juguemos un poco con el fragmento de código de arriba y bosquejemos la relación con el TDA Integer. La primera línea define tres instancias i, j y k de tipo Integer. Consecuentemente, para cada instancia, la operación especial constructor debe ser llamada. En nuestro ejemplo, esto se hace internamente por el compilador. El compilador reserva memoria para almacenar el valor de un integer y le "ata" el nombre correspondiente. Si haces referencia a i, realmente te refieres al área de memoria que se "construyó" por la definición de i. Opcionalmente, los compiladores pueden escoger inicializar la memoria, por ejemplo, podrían darle el valor de 0 (cero).

La línea siguiente

  i = 1;

le da a i el valor de 1. Por lo tanto, podemos describir esta línea con ayuda de la notación del TDA del siguiente modo :


Ejecuta la operación set (poner, establecer) con argumento 1 sobre la instacia de Integer i. Esto se escribe como sigue : i.set(1).


Tenemos ahora una representación en dos niveles. El primer nivel es el nivel del TDA, donde expresamos todo lo que se hace a una instancia de este TDA por medio de la invocación de operaciones definidas. En este nivel, pre- y postcondiciones son usadas para describir lo que sucede realmente. En el siguiente ejemplo, estas condiciones se encierran entre llaves.

{ Precondición: i = n donde n es cualquier Integer }
i.set(1)
{ Postcondición: i = 1 }
¡No olvidar que en este momento hablamos acerca del nivel del TDA ! Por consecuencia, las condiciones son condiciones matemáticas.

El segundo nivel es el nivel de la implementación, donde una representation real es seleccionada para la operación. En C, el signo igual "=" implementa la operación set(). Sin embargo, en Pascal se escogió la siguiente representación :

  i := 1;

En cualquiera de los dos casos, se implementa la operación set del TDA.

Hagamos un poquito más de hincapié en estos niveles y veamos la línea

  k = i + j;

Obviamente, "+" se escogió para implementar la operación add (sumar). Podríamos leer la parte "i + j" como "suma el valor de j al valor de i'', asi, al nivel de TDA, esto resulta en

{ Precondición: Sea i = n1 y j = n2 con n1, n2 Integers particulares }
i.add(j)
{ Postcondición: i = n1 y j = n2 }
La postcondición asegura que i y j no cambien sus valores. Por favor recuerda la especificación de add. Dice que un nuevo Integer es creado con el valor de la suma. Consecuentemente, debemos proveer un mecanismo de acceso a esta nueva instancia. Hacemos esto con la operación set aplicada sobre la instancia k:

{ Precondición: Sea k = n donde n es cualquier Integer }
k.set(i.add(j))
{ Postcondición: k = i + j }
Como podrás notar, algunos lenguajes de programación escogen una representación que es casi igual a la formulación matemática usada en las pre- y postcondiciones. Esto hace algunas veces que sea difícil no confundir ambos niveles.

4.2 Clase

  Una clase es una representación real de un TDA. Por lo tanto, provee detalles de implementación para la estructura de datos utilizada y las operaciones. Jugamos con el TDA Integer y diseñamos nuestra propia clase para éste:

  class Integer {
  attributes:
    int i

  methods:
    setValue(int n)
    Integer addValue(Integer j)
  }

En el ejemplo de arriba, así como en los ejemplos siguientes, usamos una notación que no pertenece a ningún lenguaje de programación específicamente. En esta notación class {...} denota la definición de una clase. En medio de las llaves hay dos secciones, atributos: y métodos: que definen la implementación de la estrutuctura de datos y operaciones del TDA correspondiente. Nuevamente, distinguimos los dos niveles con diferentes términos : Al nivel de implementación hablamos de "atributos", que son elementos de la estructura de datos al nivel del TDA. Lo mismo se aplica a "métodos", que es la implementación de las operaciones del TDA.

En nuestro ejemplo, la estructura de datos consiste de solamente un elemento : una secuencia de dígitos con signo. El atributo correspondiente es un integer ordinario de un lenguaje de programación [*]. Nosotros solamente definimos dos métodos setValue() y addValue() representando las dos operaciones set and add.

Definición (Clase) Una clase es la implementación de un tipo de datos abstracto (TDA). Define atributos y métodos que implementan la estructura de datos y operaciones del TDA, respectivamente. Las instancias de las clases son llamadas objetos. Consecuentemente, las clases definen las propiedades y el comportamiento de conjuntos de objetos.

4.3 Objeto

  Recuerda el ejemplo del empleado del capítulo 3. Hemos hablado de instancias de empleados abstractos. Estas instancias son "ejemplos" reales de un empleado abstracto, de ahí que contengan valores reales para representar un empleado en particular. Llamamos a estas instancias objetos.

Los objetos son identificables en forma única por medio de un nombre. Por lo tanto, tu podrías tener dos objetos distintos con el mismo conjunto de valores. Esto es similar a los lenguajes de programación "tradicional", donde tu podrías tener digamos dos integers i y j ambos equivalentes a "2". Nótese por favor el uso de "i" y "j" en la última oración para darle nombre a los dos integers. Nos referimos al conjunto de valores en un momento en particular como el estatus del objeto.

Definición (Objeto) Un objeto es una instancia de una clase. Puede ser identificado en forma única por su nombre y define un estatus, el cuál es representado por los valores de sus atributos en un momento en particular.

El estatus de un objeto cambia de acuerdo a los métodos que le son aplicados. Nos referimos a esta posible secuencia de cambios de estatus como el comportamiento del objeto :

Definición (Comportamiento) El comportamiento de un objeto es definido por un conjunto de métodos que le pueden ser aplicados.

Tenemos presentados ahora dos conceptos principales de orientación a objetos, clase y objeto. La programación orientada a objetos es por lo tanto la implementación de tipos de datos abstractos o, en palabras más sencillas, la escritura de clases. En "runtime", instancias de estas clases -los objetos- cumplen con el objetivo del programa cambiando sus estatus. Por consecuencia, tu puedes pensar que la corrida de tu programa constituye una colección de objetos. Se genera la pregunta : ¿ Cómo interactúan estos objetos? De modo que introducimos el concepto de mensaje en la sección siguiente.

4.4 Mensaje

  Un programa en ejecución es una colección de objetos, donde dichos objetos interactuantes son creados y destruídos. Esta interacción se basa en mensajes que son mandados de un objeto a otro, donde el emisor le pide al receptor que aplique un método a sí mismo. Para proporcionarte una comprensión acerca de esta comunicación, regresemos a la clase Integer presentada en la sección 4.2. En nuestro pseudo lenguaje de programación, nosotros podíamos crear nuevos objetos e invocar métodos sobre ellos. Por ejemplo, podíamos usar

  Integer i;     /* Definir un nuevo objeto integer */
  i.setValue(1);  /* Ponerle el valor 1 */

para expresar el hecho de que el objeto integer i debería poner su valor a 1. Este es el mensaje "Aplica el método setValue con argumento 1 sobre tí mismo." enviado al objeto i. Nosotros usamos la notación "." para el envío de un mensaje. Esta notación se usa también en C++ ; otros lenguajes orientados a objetos pueden usar otras notaciones, por ejemplo " -$\gt$".

Mandar un mensaje pidiéndole a un objeto que aplique un método es similar a una llamada a un procedimiento en lenguajes de programación "tradicionales". Sin embargo, en orientación a objetos, hay un cuadro de objetos autónomos que se comunican unos con los otros por medio de el intercambio de mensajes. Los objetos reaccionan cuando reciben mensajes por medio de la aplicación de métodos sobre si mismos. También pueden negar la ejecución de un método, por ejemplo si el objeto que hace la llamada no tiene permiso para ejecutar el método solicitado.

En nuestro ejemplo, el mensaje y el método que debía ser aplicado una vez que el mensaje se hubiera recibido, tienen el mismo nombre : Nosotros mandamos "setValue con argumento 1" al objeto i el cuál aplica "setValue(1)".

Definición (Mensaje) Un mensaje es una solicitud a un objeto para invocar uno de sus métodos. Un mensaje por lo tanto contiene

Por consecuencia, la invocación de un método es solamente una reacción causada por el hecho de recibir un mensaje. Esto solamente es posible si el método es realmente conocido por el objeto.

Definición (Método) Un método está asociado a una clase. Un objeto invoca un método como una reacción al recibir un mensaje.

4.5 Sumario

Ver un programa como una colección de objetos interactuantes es un principio fundamental en la programación orientada a objetos. Los objetos en esta colección reaccionan al recibir mensajes, cambiando su estatus de acuerdo a la invocación de métodos que a su vez pdrían causar que otros mensajes fueran enviados a otros objetos. Esto se ilustra en la Figura 4.1.


 
Figura 4.1:  Un programa consistente en cuatro objetos.
\begin{figure}
{\centerline{
\psfig {file=FIGS/program1.eps,width=5cm}
}}\end{figure}

En esta figura, el programa consiste en solamente cuatro objetos. Estos objetos se mandan mensajes unos a otros, como se indica por las flechas. Nótese que el tercer objeto se manda un mensaje a sí mismo.

¿Cómo nos ayuda esto en el desarrollo de software ? Para responder a esta pregunta, recordemos como hemos desarrollado software con lenguajes de programación procedimentales. El primer paso era dividir el problema en fragmentos manejables más pequeños. Típicamente, estos fragmentos estaban orientados a los procedimientos que tomaban lugar para resolver el problema, más que a los datos involucrados.

Como ejemplo, considera tu computadora. Especialmente, como un caracter aparece en la pantalla cuando oprimes una tecla. En un ambiente procedimental, tu escribes los varios pasos necesarios necesarios para desplegar un carácter en la pantalla :

1.
esperar, hasta que una tecla es presionada.
2.
obtener el valor de la tecla
3.
escribir el valor de la tecla en la posción actual del cursor
4.
avanzar la poscición del cursor

Tu no distingues entidades con propiedades bien definidas y comportamiento bien definido. En un ambiente orientado a objetos, tu harías distinción entre los objetos interactuantes tecla y pantalla. Una vez que una tecla recibe un mensaje de cambiar su estatus a "estar presionada", su objeto correspondiente manda un mensaje al objeto que representa a la pantalla. Este mensaje le solicita al objeto pantalla que despliegue el valor asociado a la tecla presionada.

4.6 Ejercicios

1.
Clase.
(a)
¿Qué distingue una clase de un TDA?
(b)
Diseña una clase para el TDA Complex. ¿Qué representaciones escoges para las operaciones del TDA ? ¿Por qué ?
2.
Objetos interactuantes. Echa un vistazo a las tareas de tu vida diaria. Escoge una que no involucre muchos pasos (por ejemplo, ver la TV, preparar un alimento, etc.). Describe esta tarea en forma procedimental y en forma orientada a objetos. Trata de empezar a ver el mundo como consistente en objetos.
3.
Perspectiva de Objetos. De acuerdo al último ejercicio, ¿Qué problemas enfrentas ?
4.
Mensajes.
(a)
¿Por qué hablamos de "mensajes" más que de "llamadas a procedimientos" ?
(b)
Menciona algunos mensajes que tienen sentido en el ambiente de Internet. (Debes por lo tanto identificar objetos.)
(c)
¿Por qué el término "mensaje" tiene más sentido en el ambiente del último ejercicio, que el término "llamada a procedimiento" ?

next up previous
Siguiente: 5 Más Conceptos de Orientación a Objetos Arriba: Introducción a la Programación Orientada a Objetos Anterior: 3 Tipos de Datos Abstractos
P. Mueller
8/31/1997