Está en la página 1de 83

Programacin

orientada a objetos
y tcnicas avanzadas de
programacin

Carlos Fontela
2003

CARLOS FONTELA

-2 -

PROGRAMACIN ORIENTADA A OBJETOS

1. PRLOGO
Empec a escribir esta obra como tercer tomo del Curso de Programacin 1 , cuyos volmenes I y II
salieron en 19992 . Pero pronto se fue convirtiendo en un texto independiente de aqullos, por varias razones.
De todas maneras, es heredera de aquella obra en cuanto a que utiliza una metodologa similar.
Adems, presumo que el lector maneja la mayor parte de los conceptos enseados en la misma, como
programacin estructurada y modular, el lenguaje Pascal y preferiblemente tambin C.
Asimismo, tambin inclu temas que estn ligados a la forma en que enseo la materia Algoritmos y
Programacin III en la Facultad de Ingeniera de la Universidad de Buenos Aires.
Finalmente, la versin preliminar de esta obra apareci en dos partes, en septiembre y noviembre de
2002, respectivamente.
Este libro se pudo haber denominado Programacin Superior. Si bien el ttulo parece un poco
pretencioso, sirve como ltimo curso de programacin para personas que manejen el paradigma estructurado.
Encara, desde la ptica de la programacin orientada a objetos, una serie de problemas de programacin de
cierta complejidad que hacen que slo se puedan analizar una vez afianzados los conceptos bsicos de
programacin.
En este sentido, este no es un libro en el cual se ensee a programar empezando por el paradigma de
objetos. Ese es un desafo que pienso acometer alguna vez.
Por qu programacin orientada a objetos? Desde el comienzo de la programacin, todos los
lenguajes tratan de abstraer. Los ms antiguos abstraen haciendo un modelo de la mquina subyacente, como en
el caso extremo de Assembler. Algunos se basan en su particular visin del mundo, como Lisp, Prolog, APL,
Cobol y RPG. Los ms modernos intentar hacer un modelo del problema a resolver. La programacin orientada
a objetos es el caso ms reciente de intentarlo desde un propsito general, e intenta describir las soluciones en
trminos de cada problema. Pero este paradigma tie ne sentido si se trata de un desarrollo mediano: no tiene
sentido escribir un programa tipo hello, world 3 con objetos.
Esta obra no se queda slo en la programacin orientada a objetos. Analizaremos tambin
programacin por eventos, como aplicacin de los objetos y conceptos de programacin en interfaces de
usuario grficas. Asimismo, exploraremos los temas de persistencia, pruebas y documentacin, desde el punto
de vista de la programacin orientada a objetos, y veremos el uso de algunos de los diagramas que utiliza el
lenguaje unificado de modelado UML.
Mi experiencia enseando programacin orientada a objetos, con eventos e interfaz de usuario
grfica me mostr las diferencias y semejanzas que existen en los lenguajes que la implementan, y desde ese
punto de vista, me pareci interesante ejemplificar sobre tres de ellos. He mechado con ejemplos en los tres,
indistintamente, y se han explicado los distintos conceptos aplicndolos a los tres lenguajes.
Como lenguajes, hemos elegido los tres ms populares, aun sabiendo que provienen de un tronco
comn 4 : Object Pascal, C++ y Java. Y hemos explicado los conceptos utilizando los tres indistintamente, sobre
todo porque esto nos permite analizar diferentes soluciones y mostrar semnticas y funcionalidades que pueden
no ser caractersticas de todos los lenguajes.
Para un aprendizaje ms veloz, recomendamos a quienes manejen bien Pascal que vean primero las
implementaciones en Object Pascal. Quienes manejen bien C, podrn optar por Java, ms orientado a objetos, y
C++, ms parecido a C. De todas maneras, creo que es perfectamente posible leer las tres variantes y sera
importante para captar las diferentes visiones sobre cada tema.
1

Curso de Programacin, Carlos Fontela, Centro de Estudiantes de Ingeniera La Lnea Recta, Buenos Aires, 1999.
El tomo III haba quedado en una versin preliminar que finalmente abandon totalmente.
3
Es un clsico de los libros de programacin aunque no de los mos empezar la enseanza de un lenguaje con un programa que
emite un saludo que dice: Hello, World.
4
Todos son herederos de la programacin estructurada.
2

-3-

CARLOS FONTELA

Cuando en el libro decimos Java nos referimos a la versin 2 del lenguaje, C++ es el de la definicin
del estndar ISO C++ de 2000, que ampli considerablemente el C++ del libro de Stroustrup [4], y Object
Pascal es el utilizado en Borland Delphi 6 o Kylix 3.
Parafraseando a Humpty Dumpty 5 , cuando uso una palabra en el texto, significa exactamente lo que
quiero que signifique, ni ms ni menos. Creo que este es un principio fundamental cuando se ensean
conceptos. Esto me oblig a ser ms preciso al separar los conceptos de sobrecarga y redefinicin, que en obras
anteriores haban sido utilizados como trminos equivalentes, o los de definicin y declaracin.
La obra no fue pensada para ser utilizada como texto de referencia, por lo que contiene numerosas
vinculaciones entre sus temas, y se supone que se lee en forma secuencial.
Esta versin cuenta con unos cuantos ejercicios resueltos. Sin embargo, a las soluciones las he
separado del texto principal ponindolas en apndices, de modo que no entorpezcan el estudio de los conceptos
tericos.
Al final del libro se presenta la bibliografa con la que trabaj y que puede servir de consulta para los
lectores. En los casos de libros que estn publicados en la Web prefer citar las ediciones en papel, sobre todo
por la volatilidad de las direcciones electrnicas. En los casos en que slo cont con direcciones de la Web, las
cit de todos modos, con la esperanza de que si deciden mudarlas se puedan encontrar fcilmente con un
buscador el da de maana.
Quiero agradecer a todos los docentes auxiliares y alumnos que he tenido en la Facultad de
Ingeniera de la Universidad de Buenos Aires, en la Universidad Catlica Argentina y en otros mbitos, que me
han hecho llegar ideas y crticas respecto de las otras obras similares y de la forma de encarar los temas.
Especialmente quiero agradecer a Francisco Rey y Javier Macchi, de quienes tom el contenido de
gran parte del captulo de programacin por eventos, y a Pablo Surez, a quien le debo una porcin ms que
considerable del captulo de pruebas.
Le dedico la obra a mi mujer, Ana, y a mis hijos, Joaqun y Clara.
Desde ya, cualquier observacin o crtica que los lectores crean conveniente hacerme llegar, ser
bienvenida y ayudar a mejorar futuras ediciones.
Carlos Fontela
Buenos Aires, marzo de 2003
5

El personaje de Lewis Carroll.

-4 -

PROGRAMACIN ORIENTADA A OBJETOS

NDICE DE CONTENIDOS
1.

Prlogo

PARTE I: PROGRAMACIN ORIENTADA A OBJETOS

2.

Introduccin: la orientacin a objetos


Conceptos previos
Programacin estructurada
Programacin modular
Abstraccin
Ocultamiento de implementacin
Hacia un nuevo paradigma
Calidad del software
Orientacin a objetos
Reduccin de la brecha entre el mundo de los problemas y el mundo de los modelos
Aumento del nivel de complejidad de los sistemas
Reutilizacin y extensin del cdigo
Uso de prototipos
Programacin en ambientes de interfaz de usuario grfica
Programacin por eventos
Programacin orientada a objetos
Significado
Lenguajes de programacin orientada a objetos
Herramientas visuales y de desarrollo rpido de aplicaciones

9
9
9
10
10
11
13
14
14
15
16
16
16
17
17
17
17
18
19

3.

Programacin orientada a objetos: generalidades y encapsulamiento


Objetos y clases
Objetos
Clases
Encapsulamiento
La abstraccin en programacin orientada a objetos
El ocultamiento en programacin orientada a objetos
Encapsulamiento
Tipos especiales de atributos
Atributos de clase
Atributos con valor constante
Atributos con restricciones
Mtodos de clase
Terminologa de objetos
Estados, eventos y transiciones
Operaciones
Estado observable de un objeto
Pasaje por valor y por referencia en programacin orientada a objetos
Constructores
Destructores
Sobrecarga
Implementacin de objetos y clases en distintos lenguajes
Objetos y clases en Object Pascal
Objetos y clases en C++
Objetos y clases en Java
Ejercicio resuelto: implementacin de nmeros racionales
Enunciado

21
21
21
22
22
22
23
23
23
23
24
24
24
24
25
25
25
26
26
26
26
28
28
30
32
34
34

-5-

CARLOS FONTELA

Solucin en Object Pascal


Solucin en C++
Solucin en Java
Ejercicio resuelto: implementacin de conjuntos
Enunciado
Solucin en Object Pascal
Solucin en C++
Solucin en Java

34
34
34
35
35
35
35
35

4.

Programacin orientada a objetos: reutilizacin y extensin del cdigo


Reutilizacin con composicin
Composicin
Agregacin
Reutilizacin con herencia
Definicin y ejemplos
Utilizacin de herencia
Herencia mltiple
Herencia con excepciones
Especializacin con menos atributos
Constructores, destructores, herencia y composicin
Atributos y mtodos protegidos
Generalizacin, especializacin e instanciacin
Interfaces
Concepto de interfaz
Un ejemplo de interfaces: la clase adaptadora
Eleccin de implementacin: composicin, herencia o interfaces?
Implementacin de reutilizacin del cdigo en distintos lenguajes
Composicin, herencia e interfaces en Object Pascal
Composicin y herencia simple y mltiple en C++
Composicin, herencia e interfaces en Java
Ejercicio resuelto: implementacin de matrices
Enunciado
Solucin en Object Pascal
Solucin en C++
Solucin en Java
Ejercicio resuelto: uso de la implementacin de matrices
Enunciado
Solucin en Object Pascal
Solucin en C++
Solucin en Java

36
36
36
37
37
37
39
40
41
41
41
42
42
42
42
43
45
45
45
46
47
49
49
49
49
49
50
50
50
50
50

5.

Programacin orientada a objetos: polimorfismo


Polimorfismo
Polimorfismo y vinculacin tarda
Redefinicin
Sobrecarga y redefinicin
Objetos polimorfos o conversin de tipo automtica
Mtodos virtuales
Constructores y destructores virtuales
Grados de polimorfismo
Clases y mtodos abstractos
Clases abstractas
Mtodos abstractos
Clases utilitarias y clases sin estado
Uso de informacin de tipos en tiempo de ejecucin

51
51
51
51
52
52
53
54
55
55
55
56
56
57

-6 -

PROGRAMACIN ORIENTADA A OBJETOS

6.

Transformacin de tipos
Moldeo automtico y moldeo explcito
Datos estructurados con elementos de varios tipos
Informacin de tipos en tiempo de ejecucin
Implementacin del polimorfismo en distintos lenguajes
Polimorfismo y otros aspectos en Object Pascal
Polimorfismo y otros aspectos en C++
Polimorfismo y otros aspectos en Java
Ejercicio resuelto: propiedades de una inmobiliaria
Enunciado
Solucin en Object Pascal
Solucin en C++
Solucin en Java
Ejercicio resuelto: uso de la implementacin de la inmobiliaria
Enunciado
Solucin en Object Pascal
Solucin en C++
Solucin en Java

57
57
58
59
60
60
61
62
63
63
63
63
63
63
63
63
63
63

Documenta ndo la programacin


Documentacin en general
UML para documentar la programacin
UML
Diagramas de clases
Diagramas de secuencia
Diagramas de estados
Diagra mas de actividades
Diagramas y programas
Documentacin interna
Documentacin interna de la programacin
El caso de javadoc
Estndares de nomenclatura
Ejercicio resuelto: diagramas de actividades, clases y secuencia
Enunciado
Solucin
Ejercicio resuelto: un diagrama de estados
Enunciado
Solucin

64
64
64
64
66
70
71
72
75
75
75
75
77
78
78
79
82
82
83

-7-

CARLOS FONTELA

Parte I: Programacin
orientada a objetos

-8 -

PROGRAMACIN ORIENTADA A OBJETOS

2. INTRODUCCIN: LA ORIENTACIN A OBJETOS


CONCEPTOS PREVIOS
Hay una serie de tcnicas, anteriores en el tiempo a la orientacin a objetos, que han tenido una
fuerte influencia sobre la misma. Entre ellas, la programacin estructurada, la programacin modular, la
abstraccin y el ocultamiento de informacin. Dado que, si bien son tcnicas desarrolladas fuera del paradigma
de objetos, permanecen en l, las vamos a repasar a continuacin.
Programacin estructurada
La programacin estructurada es un concepto que surge como respuesta a la crisis del software de los
aos 60, cuando el desarrollo de programas estaba ocupando una porcin cada vez mayor de los costos de
computacin y, a su vez, el mantenimiento de los mismos era cada vez ms inmanejable.
La programacin estructurada se convirti, hace unos 15 aos, en un must, y todo producto que se
lanzaba al mercado se proclamaba estructurado.
El primer inconveniente que se atac fue el uso del ya olvidado Goto 6 , sobre todo luego de un
artculo de Dijkstra titulado Goto considered harmful (El Goto considerado daino). A menudo se ha
resumido la programacin estructurada como el rechazo del Goto y nada ms.
Esta bsqueda de la supresin del uso del Goto haba provocado la enunciacin del teorema de
Bohm-Jacopini [13], ya en 1966, bajo la caracterizacin de una entrada, una salida: "Cualquier segmento de
programa con una entrada y una salida que tenga todas las proposiciones en algn camino de la entrada a la
salida se puede especificar usando slo secuencia, seleccin e iteracin".
Sin embargo, dentro de los propsitos de la programacin estructurada haba otros, de los cuales los
ms importantes parecen ser:
?? Utilizar un estilo disciplinado de programacin.
?? Ser una tcnica que lleve a programas altamente modificables.
?? Sencillez, claridad y elegancia.
Estos objetivos se logran slo parcialmente con la eliminacin del Goto y su reemplazo por las tres
estructuras fundamentales de secuencia, seleccin e iteracin.
Otros aspectos, menos formalizados, apuntaban a usar lenguajes que poseyeran unas pocas sentencias
de uso habitual, con construcciones conceptualmente simples y ampliamente aplicables en la prctica, sin reglas
demasiado permisivas, el uso de nombres claros, no utilizar un identificador para propsitos mltiples,
abundancia de comentarios aclaratorios, uso de sangra para aumentar la legibilidad y denotar la estructura del
programa, el aislamiento de las dependencias de la mquina en unas cuantas rutinas separadas, etc..
Fue la primera vez que el rendimiento y las caractersticas tcnicas dejaron de ser las nicas
consideraciones de calidad de los sistemas de software.
Los lenguajes de programacin como Fortran y Algol se hicieron ms estructurados, y luego
surgieron nuevos lenguajes, como C y Pascal.
El concepto de programacin estructurada lo he analizado a fondo en mi obra Curso de
Programacin [5], en el tomo I.
6

Ms correctamente, ruptura de secuencia o interrupcin incondicional de la secuencia.

-9-

CARLOS FONTELA

Programacin modular
La llamada programacin modular busc cubrir los baches que dejaba la simple aplicacin de la
programacin estructurada, sobre todo en el desarrollo de sistemas de tamao medio a grande, aunque buscaba
objetivos similares.
La idea consisti en dividir un programa en un conjunto de mdulos o subprogramas autnomos que
fueran individualmente programables, verificables y modificables. En muchos casos estos mdulos fueron
desarrollados por distintos programadores y eran testeados y mantenidos en forma independiente.
Cuando se elige desarrollar el sistema haciendo un refinamiento de un problema desde lo ms
complejo a lo ms elemental, el mismo se escribe como una secuencia de acciones no primitivas que luego son
desarrolladas como subprogramas. Esto se conoce como programacin "top-down" o descendente, el primer
estilo encarado en el marco de la programacin modular.
En otros casos los subprogramas sirven para escribir una serie de acciones no primitivas, de uso
relativamente frecuente, que luego se usan en varios programas, constituyendo lo que se conoce con el nombre
de biblioteca de subprogramas. Estas bibliotecas (en ingls "libraries"7 ) pueden ser tan amplias que los
programadores escriban programas en un lenguaje casi propio, que permite aun el manejo de ciertos tipos y
estructuras de datos que el lenguaje original no manejaba. A menudo esto es llamado programacin "bottomup" o ascendente, y pronto se convirti, no en un sucedneo de la programacin descendente, sino en su mejor
complemento.
Es tambin de gran utilidad la divisin de un programa en mdulos en la etapa de prueba, pues cada
subprograma puede ser probado en forma separada antes de integrarlos al sistema. Esto permite que en el
momento de la integracin del sistema se pueda tener la seguridad de que cada uno de los mdulos no posea
errores internos, restando solamente la prueba en conjunto para ver la interaccin entre los mismos.
El adecuado uso de mdulos permite tambin un mejor mantenimiento, ya que si se necesita
modificar alguna tarea de las que efecta el sistema, esto se podr hacer modificando el mdulo que realiza
dicha tarea, sin necesidad de tocar todo el programa.
Se enfatiza asimismo el uso de declaraciones locales, que confina identificadores a espacios de
nombres ms reducidos, y se desalienta el de identificadores globales, sobre todo cuando se trata de variables.
En esta misma lnea, se recomienda que las interacciones entre mdulos se limiten al pasaje de parmetros.
Otras recomendaciones apuntan a reducir el acoplamiento entre mdulos y aumentar la cohesin.
Esto es, garantizar que cada mdulo tenga la menor cantidad de interacciones posibles con los dems mdulos
(conexiones angostas), a la vez que cada uno debe hacer una sola cosa simple, trabajando sobre la misma
estructura de datos.
Las modificaciones en lenguajes de programacin que apuntaban a la programacin estructurada
tambin implementaron la programacin modular. As, Fortran 77, Algol 80, Pascal y C, manejaban mejor la
modularidad que sus predecesores.
El concepto de programacin modular tambin fue introducido en mi obra antes mencionada, en el
tomo I. Tambin en el tomo II se analiza el tema.
Abstraccin
Pero la programacin estructurada y modular, as como estaba encarada, ya no resolva todos los
problemas a mediados de la dcada de los 80. Por eso, muchos empezaron a cuestionar por qu la industria del
software no haca lo que otras industrias, que construyen sus productos en base a componentes desarrollados
7

Esto ha dado lugar a que en general se las conozca como libreras.

- 10 -

PROGRAMACIN ORIENTADA A OBJETOS

por un tercero.
As, por ejemplo, una fbrica de automviles no pretende producir los equipos de audio o de aire
acondicionado, las bateras, las lamparitas o las cubiertas que incluye en sus modelos, y a veces ni siquiera los
motores. Por qu hacen esto? Precisamente porque comprrselos a quien produce estas autopartes en forma
masiva suele ser ms econmico, adems de que permite que cada uno se dedique a lo que mejor sabe hacer.
Lo mismo puede aplicarse al desarrollo de software, utilizando lo desarrollado por otros en nuestras
aplicaciones o incluso lo desarrollado en casa para otros sistemas. Esto se llama abstraccin.
De esta forma se puede ir construyendo un lenguaje de nivel superior. Por ejemplo, supongamos que
agregamos a Pascal una funcin de exponenciacin, que el lenguaje no tiene. Si incluimos esta funcin en una
unidad de biblioteca, podremos utilizarla luego en nuestras aplicaciones. Asimismo, si el mdulo a desarrollar
fuera ms complejo, podramos pensar en comprarlo a alguien que lo haya desarrollado.
La abstraccin se utiliza tambin para lo que se denomina implementacin de tipos de datos
abstractos (TDA). Diremos que trabajamos con un TDA cuando manejamos un tipo de dato que no est
predefinido en el lenguaje utilizado, simulndolo de manera totalmente transparente, mediante un adecuado uso
de una biblioteca de subprogramas. Esto permite manejar tipos de datos que el lenguaje no posee, ya testeados
en otros contextos.
Puesto que los tipos de datos no son conjuntos sino lgebras, es decir, conjuntos ms las operaciones
definidas sobre los elementos de los mismos, se hace necesario especificar ambas cosas. Por ello, la
implementacin de un TDA implica siempre las siguientes 3 tareas:
?? Determinacin de las operaciones necesarias sobre el TDA.
?? Eleccin de una estructura de datos sobre la cual se materializar la implementacin.
?? Implementacin de la estructura de datos y las operaciones.
Los lenguajes de programacin modulares no tenan en general un buen soporte para la abstraccin.
Slo Ada pareci reconocer esta necesidad y en algunas implementaciones de Pascal se introdujo el concepto
de unidad de biblioteca. C implement una funcionalidad incompleta.
A pesar de los aos que tiene el concepto, la abstraccin se ha utilizado en sus primeros tiempos casi
siempre dentro de una misma empresa o equipo de desarrollo, sin que se diera ese comercio de componentes de
software que se viene anunciando desde los 80. Sin embargo, desde hace un lustro aproximadamente, gracias a
la tecnologa de objetos y el auge de Internet, ha surgido este mercado que est comenzando a revolucionar el
desarrollo de software. Tal vez en unos aos ms los desarrolladores de software terminemos comprando la
mayor parte de lo que necesitemos, enchufando componentes y probndolos en conjunto.
La abstraccin de datos est analizada en el tomo II de mi obra ya citada.
Ocultamiento de implementacin
El problema del uso de la abstraccin, sobre todo si hablamos de TDA, consista en que no haba
forma de impedir que el usuario del mismo (un programador de aplicaciones que denominaremos cliente)
hiciera un uso indebido a los datos, porque tenda a utilizar conceptos propios de la implementacin que no
debieran ser de su incumbencia.
Volviendo a la analoga de la industria automotriz, quien provee a una fbrica de automviles de
equipos de audio no suele especificar cmo estn construidos los mismos. Solamente basta con que asegure una
serie de conectores o interfaces que permitan su instalacin y una serie de caractersticas y funcionalidades a
prestar. De esta manera, el fabricante del equipo de audio puede establecer cambios en los circuitos internos sin
necesidad de que el fabricante de autos deba modificar nada si se respetan las interfaces y las prestaciones
establecidas. Esto lo logra porque el equipo de audio es, desde el punto de vista de la fbrica de automviles,
una caja negra, que se testea cerrada, teniendo en cuenta solamente que cumpla las prestaciones establecidas

- 11 -

CARLOS FONTELA

por un contrato y que tenga las interfaces necesarias para poder conectarlo.
Cmo puede este concepto ser llevado a la industria del software? Con el principio del
ocultamiento de implementacin, tambin llamado ocultamiento de informacin u ocultamiento de datos.
Este concepto permite el desarrollo de software de modo tal que el cliente no pueda usar la estructura de datos y
los algoritmos subyacentes. En otras palabras, se pueden usar las interfaces de los TDA, pero no la
implementacin. De este modo, la interfaz se convierte en una especie de contrato entre las partes, que debe ser
respetado.
El ocultamiento de implementacin precisa un par de normas respecto de la especificacin 8 :
?? Al cliente, se le debe proveer slo toda la informacin que necesita para usar el mdulo
correctamente.
?? Al que implemente el mdulo, se le debe proveer toda la informacin necesaria para
comprender el uso que se har del mismo, pero ninguna informacin ms.
Por lo tanto, una especificacin debe sealar cules son las funciones que el mdulo realiza,
describiendo el dominio de cada una, los valores iniciales, los parmetros que se deben utilizar y el efecto de
dichas funciones.
El ocultamiento implica separar el qu del cmo. Es decir, el cliente debe conocer qu hace el
mdulo, pero no necesariamente cmo lo hace.
Todo esto puede parecer extrao: por qu ocultarle al usuario de la biblioteca lo que no necesita?
Las ventajas del ocultamiento son bsicamente dos:
?? Permitir cambios de implementacin.
?? Impedir violaciones de restricciones entre datos internos.
La primera ventaja se refiere a que, por no poder usar el cliente la estructura de los datos y
algoritmos, no va a utilizar propiedades exclusivas de stos, de modo que en futuras modificaciones se podr
alterar dicha estructura sin que sean necesarios cambios en los programas clientes.
Por ejemplo, si se desarrolla un TDA que maneja pilas de enteros trabajando sobre arreglos, y se le
da al cliente acceso a la impleme ntacin, ste puede utilizar facilidades propias de la forma de implementacin.
Si luego, por consideraciones diversas, se establece que conviene implementar las pilas sobre listas
encadenadas, no podr hacerse sin obligar al cliente a modificar sus programas, lo cual alterara el contrato
entre implementador y cliente.
Ntese, en consecuencia, que de no ocultar la implementacin, se estara impidiendo su evolucin.
La segunda ventaja que se mencion se refiere a las restricciones que pueda haber entre datos
internos, que hayan sido establecidas por el implementador como resguardo para el buen funcionamiento, y que
puedan ser arruinadas por el acceso indebido del cliente.
Por ejemplo, si el implementador establece tres datos de un TDA vinculados entre s, dejar librado el
acceso a la implementacin al cliente puede arruinar el trabajo hecho. Un ejemplo de esto puede ser un grafo no
dirigido implementado de forma tal que por cada arco que se agrega en un sentido se agrega automticamente
su simtrico, y cada vez que se elimina un arco se eliminan ambos. Un cliente que no entiende del todo la
implementacin puede intentar agregar o suprimir un arco sin preocuparse por la simetra.
De todas maneras, es importante destacar que el ocultamiento de implementacin debe ser cuidadoso
en respetar el contrato entre cliente e implementador en todo momento. Vale decir, las versiones futuras de un
mismo TDA o mdulo deben tener, por lo menos, la misma funcionalidad y la misma interfaz que la primera
versin, y no introducir efectos colaterales. Por lo tanto, podr agregar nuevas operaciones, pero debo
garantizar que las antiguas operaciones permanecen y mantienen la misma interfaz.
8

Esto lo tom de Boria [11].

- 12 -

PROGRAMACIN ORIENTADA A OBJETOS

Asimismo, la implementacin debe respetar en todo momento las restricciones entre datos internos
que sean necesarias.
Adems, para que sea til al cliente, toda la funcionalidad esperable de un TDA debera estar
accesible en forma de subprogramas. Decimos en este caso que la implementacin es completa . Por eso suele
ocurrir que se le oculta al usuario la estructura interna de un TDA y las implementaciones de los mdulos, pero
se le deja ver el encabezado de estos ltimos.
En definitiva, se oculta la implementacin para que ningn cliente sea dependiente de una forma de
implementacin en particular. O dicho de otro modo, para que el cliente pueda estar seguro de que est usando
el TDA correctamente, y el implementador pueda introducir cambios y mejoras en el futuro.
El concepto de ocultamiento de implementacin slo se dio en algunos lenguajes, como Ada y
Modula -2, antes del surgimiento de la programacin orientada a objetos.
Hacia un nuevo paradigma
La gran pregunta que cabe hacerse es, despus de todo lo visto, por qu seguimos buscando nuevas
tcnicas de desarrollo?
El problema principal es que la crisis del software sigue, y probablemente no terminar nunca. Una
de las causas ms fuertes es la huida hacia adelante 9 que se verifica por el aumento de complejidad de los
sistemas. As, cuando una tcnica estaba resultando til, el enorme crecimiento de la complejidad la hace
obsoleta.
Esto es bastante lgico si lo pensamos humana y tecnolgicamente. Cuando las computadoras eran
muy caras y el costo de desarrollar software muy alto, los programas resolvan tareas elementales. A medida
que el costo del hardware baj, surgieron nuevos lenguajes de programacin y hubo tcnicas mejores de
desarrollo de software, se pudieron crear sistemas cada vez ms complejos, por lo que esos hardware, lenguajes
y tcnicas resultaron insuficientes. Con el tiempo el hardware sigui abaratndose, surgieron ambientes de
desarrollo amigables y se crearon metodologas de desarrollo que permitieran manejar la complejidad que se
estaba precisando, pero los requerimientos crecieron en complejidad. Es obvio que una crisis as no va a
finalizar nunca (aunque personalmente creo que se debera hacer todo lo posible por acotarla ).
Desde el punto de vista de la complejidad y del riesgo de error, podemos hablar de categoras de
aplicaciones. En primer lugar, estaran los programas aficionados, que son los que se hacen por individuos
dentro de grupos que comparten intereses comunes, como los estudiantes: entre stos, el costo del error es bajo
y el desarrollo es econmico. Luego vendran los programas renovables o de consumo, como los tpicos
productos de procesamiento de textos y planillas de clculo, de un diseo con poca interaccin con el usuario
real, muy econmicos por su gran difusin, y de escasos riesgos en caso de errores. Le siguen los llamados
sistemas esenciales, que seran aquellos que con sus fallas pueden poner en peligro el funcionamiento de una
empresa. Y finalmente, los sistemas vitales, de los que depende la vida de seres humanos o los que pueden
poner en peligro la vida humana. Evidentemente, cuanto mayor es el riesgo de error, mayor es la complejidad,
pues las salvaguardias para evitar errores introducen gran cantidad de cdigo y relaciones entre mdulos.
El aumento de la complejidad no es un asunto trivial. Si pensamos, haciendo una grosera
simplificacin, que cada nueva funcionalidad agregada a un producto de software agrega un nuevo mdulo que
implemente esa funcionalidad, podemos medir el aumento de complejidad asimilndolo al aumento del nmero
de mdulos. Pero, como sabemos, la cantidad de interacciones posibles entre mdulos crece mucho ms que
linealmente con stos, y es del orden del cuadrado del nmero de mdulos 10 .
Encima, lo usual es enfrentar la complejidad, no intentando escribir la menor cantidad de cdigo
posible, sino que se suele traducir en un aumento, a veces innecesario, del tamao del cdigo.
Otras razones para el uso de nuevas tcnicas de desarrollo tienen que ver con nuevos usos de la
9

La expresin la tom de Muller [10].


Hoy en da existen mtricas para evaluar la complejidad, pero en este contexto preferimos este anlisis simplificado.

10

- 13 -

CARLOS FONTELA

informtica o nuevas formas de uso. Por ejemplo, el auge de las interfaces grficas de usuario, sobre todo luego
de 1995, ha impulsado nuevas formas de desarrollo, entre ellas la programacin visual y la programacin por
eventos. La World Wide Web tambin ha impulsado la aparicin de aplicaciones especiales para ese medio.
Estas tcnicas, a su vez, precisan de nuevas metodologas de desarrollo y programacin.
Calidad del software
El objetivo primordial de la orientacin a objetos es la calidad. Todo lo dems le est subordinado.
Para entender la importancia de la calidad, mencionemos el problema del ao 2000. Debido a este
grueso error de diseo, que muchos informticos tratan intilmente de justificar, se gastaron miles de millones
de dlares en todo el mundo en mantenimiento correctivo. Hemos pensado en los usos alternativos que pudo
haber tenido esa cantidad de dinero?
La calidad del software est influenciada tanto por factores internos, que son aqullos que slo
afectan a los informticos, y externos, que perciben los usuarios finales. Estos ltimos son los nicos realmente
importantes, y los primeros deben ser condicin para que se den estos.
A continuacin presento una lista de factores, de ms a menos importantes:
?? Confiabilidad. ste es el factor de calidad por excelencia. Se basa a su vez en dos necesidades:
correccin (que el sistema cumpla con las especificaciones) y robustez (capacidad de reaccionar
bien ante situaciones excepcionales).
?? Extensibilidad: es la facilidad de adaptarse a cambios de especificacin.
?? Reutilizacin: es la capacidad de las partes de un sistema para servir en la construccin de
aplicaciones distintas.
?? Compatibilidad: se refiere a la interoperabilidad con otros productos de software, y se logra a
travs del uso de estndares, como las normas de comunicacin, formatos de archivos, etc..
?? Facilidad de uso o usabilidad: significa que el sistema pueda ser utilizado por personas de
diferentes formaciones y capacidades.
?? Portabilidad: es la facilidad de correr el sistema en otras plataformas distintas de aquellas para las
cuales fue diseado.
?? Eficiencia. Consiste en usar la menor cantidad posible de recursos de hardware, tiempo de
procesador y ancho de banda. Este requisito de calidad no se debe exagerar, ya que, como dice
un refrn conocido, no importa cun rpido es hasta que no est correcto.
?? Funcionalidad. El sistema no debe pecar ni por exceso ni por defecto respecto de los
requerimientos. En general, conviene comenzar el desarrollo por los aspectos ms importantes, y
nunca sacrificar la calidad por agregar funcionalidad.
?? Oportunidad: que el sistema est en el mercado en el momento en que los usuarios lo precisan, o
apenas un poco antes.
?? Costo.

ORIENTACIN A OBJETOS
La tecnologa de orientacin a objetos es un nuevo paradigma de desarrollo de sistemas. Con esta
tecnologa se busca esa meta siempre inalcanzable de obtener sistemas econmicos de desarrollar y mantener11 .
En realidad, el paradigma de objetos no es nuevo en absoluto, aunque su auge periodstico haya
empezado hace unos 10 aos. Naci de la mano de los problemas de simulacin, y de lenguajes como Flavors y
11

Cuando digo "inalcanzable" me refiero a que cada unos 10 aos surgen nuevas ideas que mejoran las tcnicas que se estaban
utilizando y que supuestamente eran el ltimo escaln en este sentido.

- 14 -

PROGRAMACIN ORIENTADA A OBJETOS

Smalltalk, hace ya ms de 20 aos. Tampoco es cierto que sea una idea totalmente diferente de la
"programacin tradicional", al punto que quien quiera aprender a programar con objetos deba sepultar sus
conocimientos previos en programacin, como pretenden algunos autores apasionados por el paradigma.
Lo que se ha gestado en estos ltimos aos es una fiebre de consumo (periodstico por lo menos) de
todo lo que de alguna manera tenga algo que ver con los objetos. Y, paralelamente, han aparecido en el
mercado un sinnmero de ambientes de trabajo, ambientes de desarrollo e implementaciones de lenguajes que
se proclaman "orientados a objetos". Y eso es lo que la mayora ha odo: mucho ruido, personas que hablan de
algo que no entienden del todo y mucha confusin.
La metodologa de orientacin a objetos se impuls con una serie de objetivos, que analizaremos en
los tems subsiguientes:
?? Reduccin de la brecha entre el mundo de los problemas y el mundo de los modelos.
?? Aumento del nivel de complejidad de los sistemas.
?? Fomentar la reutilizacin y extensin del cdigo.
?? Uso de prototipos.
?? Programacin en ambientes de interfaz de usuario grfica.
?? Programacin por eventos.
Reduccin de la brecha entre el mundo de los problemas y el mundo de los modelos
La orientacin a objetos intenta crear una correspondencia unvoca entre elementos del espacio del
problema y objetos en el espacio de soluciones.
Desde la perspectiva de la orientacin a objetos, los objetos de un programa interactan para resolver
un problema, respondiendo a estmulos mensajes o eventos del medio externo (generalmente otros
objetos).
Para la mayora de las personas, la forma de pensar orientada a objetos es ms natural que las
tcnicas tradicionales. Al fin y al cabo, el mundo est formado por objetos. Comenzamos a aprender sobre ellos
en la infancia y descubrimos que se comportan de determinadas maneras: desde una etapa muy temprana
categorizamos los objetos y descubrimos su comportamiento. Las personas piensan de manera natural en
trminos de objetos, eventos y mecanismos de activacin. Y los programas no son ms que modelizaciones de
la realidad.
Miremos un poco alrededor de nosotros: las sillas en que estamos sentados, la mesa que tenemos
delante, el colectivo que nos transporta, el supermercado donde hemos ido a comprar comida, las cajas, el pollo
y los tomates que compramos, los cajeros... Estamos rodeados por objetos.
sta es una de las principales razones por las cuales los ambientes grficos se suelen proclamar como
orientados a objetos.
Si tuviramos que hacer un sistema que simulara las colas en las paradas de colectivos o los stocks
del supermercado, nadie dudara en utilizar POO. Es por ello que el primer lenguaje que tuvo cierta orientacin
a objetos fue Simula 67, un lenguaje orientado a simulacin, en la dcada del sesenta!
Un objeto es cualquier cosa, real o abstracta, acerca de la cual almacenamos datos y los mtodos que
controlan dichos datos. Son ejemplos de objetos: una empresa, un recibo, un plano de la Repblica Oriental del
Uruguay, una disquetera, un tranva, el recorrido de un tranva, un proceso para emitir un recibo, un icono en
una pantalla, toda la pantalla, este texto, un carcter del texto, etc.
En el ambiente de la POO se suele pensar en los objetos como entidades activas, que realizan tareas.
A los datos de la programacin tradicional se les aplican procesos, se les hace tal cosa, se les hace tal otra...
Cuando se trabaja con objetos son stos los que actan, estimulados por mensajes y respondiendo con el
comportamiento esperado. Se piensa en los objetos como actores en el escenario, a los cuales el programador
(autor) les define su comportamiento (papel) y el usuario (director) dirige su actuacin.

- 15 -

CARLOS FONTELA

Tambin se puede pensar en un objeto como un elemento a priori pasivo, que es despertado por la
llegada de un mensaje proveniente de otro objeto, y que responde activamente a este mensaje.
Una clase responde a la idea de concepto, entendido como una nocin compartida que se aplica a
determinados objetos en forma consciente. Un concepto puede no tener instancias, como el concepto de
elefante ovparo . Sin embargo, no puede haber objetos que no respondan a un concepto. As surge la nocin de
clase.
Desde esta perspectiva, los objetos de un programa interactan para resolver un problema,
respondiendo a estmulos mensajes o eventos del medio externo (generalmente otros objetos).
Aumento del nivel de complejidad de los sistemas
Como dijimos ms arriba, sta es una de las principales causas que provocan la continuidad de la
crisis del software. Desde el principio de esta crisis se intent atacar el problema de la complejidad, en un
principio mediante la descomposicin descendente (top-down) de un sistema, y luego incorporando la
construccin ascendente (bottom-up) de mquinas virtuales cuyas abstracciones fueran acercando el modelo al
problema en forma iterativa.
La orientacin a objetos, al reducir la brecha entre los modelos y la realidad, ya colabora en este
aspecto. Adicionalmente, un mejor manejo de los grandes bloques de cdigo, la agrupacin de TDA,
bibliotecas y dems, facilita la administracin de proyectos grandes. Tampoco es despreciable la facilidad para
el trabajo de grupos grandes de desarrolladores.
Pero lo que cambia radicalmente la tecnologa de orientacin a objetos es nuestra forma de pensar
sobre los sistemas. La complejidad de los objetos que podamos utilizar seguir en aumento, ya que nuevos
objetos se pueden construir a partir de otros. stos a su vez estn constituidos por otros objetos, y as
sucesivamente. Podemos tener una biblioteca como un depsito de clases, en parte comprada y en parte
construida en casa. Es muy probable que estas clases sean ms poderosas a medida que crece su complejidad.
De esta manera, se puede llegar a un sistema de un milln de lneas de cdigo adquiriendo novecientas mil en
el mercado y desarrollando las cien mil ms especficas de la aplicacin en cuestin.
Por todo esto hay quienes dicen que la orientacin a objetos permite ocultar la complejidad bajo la
simplicidad de los objetos.
Reutilizacin y extensin del cdigo
Llamamos reutilizacin y extensin del cdigo a la facilidad para emplear, en el desarrollo de una
aplicacin, cdigo desarrollado y probado en otros contextos. Volveremos sobre esto en captulos posteriores.
La orientacin a objetos viene incluye dos capacidades, denominadas herencia y polimorfismo, que
facilitan enormemente el uso de cdigo escrito, ya sea por el propio equipo o por terceros, sin necesidad de
copiarlo fsicamente y sin violar el principio de ocultamiento de implementacin.
A su vez, este cdigo puede ser utilizado tal como est (reutilizacin) o se le pueden incorporar
nuevas funcionalidades sin alterarlo (extensin), gracias de nuevo a la herencia y el polimorfismo.
Uso de prototipos
Como veremos ms adelante, las nuevas metodologas de desarrollo de software estn virando hacia
un desarrollo iterativo e incremental con amplia participacin de los usuarios. En este contexto, el concepto de
prototipo, como versin intencionalmente incompleta de un producto, surge con mucho nfasis.
Las tcnicas de orientacin a objetos facilitan el uso de prototipos debido a la facilidad de
implementar un sistema en forma absolutamente modular, e incluso dejar detalles de implementacin para ms
adelante. Es la caracterstica denominada encapsulamiento la que, al preocuparse ms bien de qu hace el
sistema ms que de cmo lo hace, permite dejar de lado detalles finos y concentrarse en las lneas generales del
sistema. La herencia y el polimorfismo son importantes si se posee una jerarqua de clases rica, ya que
favorecen el desarrollo veloz de clases similares a las ya existentes, trabajando siempre sobre comportamiento

- 16 -

PROGRAMACIN ORIENTADA A OBJETOS

probado.
Programacin en ambientes de interfaz de usuario grfica
Las interfaces de usuario grficas no son nuevas. Xerox lanz el primer ambiente de este tipo con la
Xerox Star en 1981. Su sucesor ms famoso fue el sistema operativo de la Macintosh de Apple, en 1984. Poco
despus surgira una interfaz de usuario que corra sobre DOS para PC, llamada GEM (1985), muy parecida al
producto de Apple , y a ella le siguieron el ambiente Windows de Microsoft (nacido en 1985 pero usado en
forma ms masiva a partir de 1990), que tambin corra sobre DOS, y el Warp del sistema operativo OS/2 de
IBM, por nombrar slo a los ms conocidos. Sin embargo, la aparicin del robusto Windows NT en 1993, la
conversin del simple ambiente Windows en sistema operativo en 1995 y, finalmente, la proliferacin de
interfaces grficas para sistemas Unix, han dado por tierra con las interfaces de lnea de comandos que parecan
inmortales hace apenas 10 aos.
Estas interfaces de usuario se conocen como WIMP (windows, icons, mouse pointer) o GUI
(graphical user interface). Y la interfaz web es un caso especial de las mismas.
Uno de los objetivos de la orientacin a objetos es facilitar el desarrollo de software para estas
plataformas GUI y web, ya que en este tipo de ambientes se manipulan ms bien objetos y no tanto procesos.
Programacin por eventos
Pero las caractersticas de las interfaces de usuario grficas no se reducen al manejo de ventanas,
iconos y el mouse, ni tampoco a su condicin grfica.
En realidad, desde el punto de vista de la programacin, su mayor novedad es la forma en que el
usuario interacta con la aplicacin, que modifica totalmente la forma tradicional secuencial en que la
computadora ejecutaba una serie de tareas a pedido del usuario y cada tanto le peda un dato para continuar. En
estos nuevos enfoques, basados en eventos, el usuario tiene toda una gama de acciones que puede realizar y la
aplicacin debe estar preparada para responder con acciones previstas pero no programadas.
Aqu la programacin orientada a objetos aporta su visin no imperativa de desarrollo, que permite
no fijarse tanto en los procesos como en los mensajes enviados por el usuario y en las respuestas de la
aplicacin a esos estmulos.

PROGRAMACIN ORIENTADA A OBJETOS


Significado
En la programacin imperativa tradicional, los algoritmos se describen en base a procesos (ya sea en
forma secuencial o mediante concurrencia). Por ejemplo, se pueden escribir en Pascal o C una serie de
subprogramas para el manejo de pantallas, y sern exactamente eso: procedimientos o funciones que describen
cmo se abre una ventana, cmo se la cierra, cmo se la limpia, etc.. As, los algoritmos se expresan mediante
procesos y stos como una secuencia de tareas a realizar por la computadora. Por eso este tipo de programacin
se llama procedimental o imperativa.
La programacin orientada a objetos (POO) encara la resolucin de cada problema desde otra ptica:
la ptica del objeto. As, para resolver el caso anterior se define un objeto pantalla y se definen todas las
acciones (denominadas mtodos) que ese objeto puede realizar (comportamiento), cada vez que se le enva un
cierto mensaje o solicitud. Las nicas acciones que se le pueden hacer a un objeto vienen dadas por los
mtodos. Lo que se define es el comportamiento de los objetos frente a mensajes o solicitudes provenientes de
otros objetos. Incluso los programas se disparan con el envo de un mensaje a un objeto.
Desde el punto de vista de los objetos, un programa es un conjunto de objetos colaborando, o bien,
un conjunto de objetos enviando mensajes y respondiendo a otros mensajes.

- 17 -

CARLOS FONTELA

Dado que esos mtodos son, en la prctica, muy similares a los procedimientos de la programacin
imperativa tradicional y los mensajes se podran pensar como invocaciones a esos procedimientos, se podra
pensar que simplemente se ha inventado un nuevo nombre para algo que ya exista anteriormente.
Esto es cierto: las ideas de objetos provienen en gran parte de la abstraccin de datos. Sin embargo,
el paradigma de objetos introduce conceptos nuevos. Adems, es una tcnica ms estructurada que los intentos
anteriores de estructuracin. Y es ms modular y abstracta que los intentos previos de abstraccin de datos y
ocultamiento de implementacin.
La POO es un paradigma de programacin no imperativa, no procedimental.
Se basa en tcnicas previas, como la abstraccin y el ocultamiento de la implementacin, e incorpora
la herencia, el polimorfismo y otras de menor entidad.
No entraremos en mayor detalle porque dedicaremos 4 captulos a este tema.
S digamos que la POO no se puede desligar de todo el paradigma de orientacin a objetos. En
efecto, no hay que confundir POO con el uso de un lenguaje que soporte POO. Para hacer buena POO hay que
desarrollar todo el sistema utilizando el paradigma, empezando por un anlisis y un diseo orientados a objetos.
Lenguajes de programacin orientada a objetos
Ms adelante haremos un examen ms detenido de los principales lenguajes de POO, una vez que
hayamos estudiado los conceptos fundamentales. Aqu solamente presentamos un esquema clasificatorio de los
mismos.
Los lenguajes que se usan para la POO se pueden clasificar de muchas maneras. Nosotros hemos
elegido una clasificacin segn su origen y afinidad con el paradigma.
En primer lugar, tenemos los denominados lenguajes puros de orientacin a objetos. Todos ellos
provienen del antiguo Simula 67 y tienen como caracterstica permitir slo objetos como tipos de datos. Entre
ellos estn:
?? Simula
?? Smalltalk
?? Eiffel
Luego existen lenguajes que permiten tanto la POO como algn tipo de programacin procedimental,
o bien que permiten algunos datos que no son objetos. Dentro de este grupo hay algunos que deriva n de los
lenguajes procedimentales estructurados Pascal, C y Ada 86 (que a su vez deriva de Pascal):
?? Objective C
?? C with classes
?? C++
?? C#
?? Clascal
?? Object Pascal
?? Ada 95
?? Modula-3
?? Java
Otros de este grupo derivan del lenguaje funcional y de listas Lisp, de gran popularidad en algunos
ambientes en la dcada de 1980 y considerablemente ms cerca de la POO que los lenguajes estructurados:
?? Loops
?? Flavors
?? Common Loops
?? CLOS

- 18 -

PROGRAMACIN ORIENTADA A OBJETOS

?? Ceyx
Finalmente, hay algunos lenguajes que permiten utilizar objetos, pero no soportan todo el paradigma
de orientacin a objetos. Algunos de ellos no permiten definir clases, otros no soportan herencia o
polimorfismo. He aqu algunos ejemplos:
?? Simula 67
?? Clu
?? Ada 86 y anteriores
?? Visual Basic (hasta versin 6)
?? Javascript
Por supuesto, hay otras maneras de clasificar a los lenguajes de POO. Una de ellas es el manejo de
tipos. En ese sentido, Ada y Eiffel son de tipeo fuerte, pues slo permiten combinar expresiones del mismo
tipo. En el mismo camino, aunque siendo menos estrictos, estn Object Pascal, Modula-3 y Java. C++, en
cambio, maneja un tipeo dbil, un poco por compatibilidad con su predecesor C. En estos lenguajes se permiten
combinar expresiones de tipos distintos y la transformacin de tipos se puede hacer casi sin restriccin. Hay
tambin lenguajes sin tipos, como Smalltalk y Python.
La discusin sobre el grado de tipeo es tan larga como la historia de la programacin. La gran ventaja
del tipeo fuerte es que, al no permitir mezclar conceptos diferentes 12 hace ms fcil la depuracin y el
mantenimiento. Sin embargo, los lenguajes de tipos dbiles o sin tipos permiten generar aplicaciones pequeas
muy rpidamente, y por lo tanto son candidatos ideales para construir prototipos.
En el curso, como ya he dicho en el prlogo, utilizamos los lenguajes Object Pascal, C++ y Java.
Sabemos que son lenguajes que tienen sus races en otros paradigmas, pero precisamente es el paradigma que
presumimos que manejan nuestros lectores. Pensamos que ensear Simula, Smalltalk, Eiffel o cualquier otro
lenguaje hara ms difcil el seguimiento por parte de ellos. Si este fuera un primer curso de programacin
deberamos quedarnos con un lenguaje de POO puro, que permita pasar de los conceptos al cdigo de manera
natural, como ocurra con Pascal en la programacin estructurada, y dejar para un segundo curso el estudio de
lenguajes hbridos de uso comercial.
A menudo he mostrado la evolucin de una idea a partir de Pascal o Ada. Pascal, por ser un lenguaje
archiconocido en el mbito de la programacin estructurada. Ada, porque es fuente de muchos avances que
luego llegaron con los objetos, al punto que el fracaso de Ada tuvo que ver en gran parte con que cuando el
mercado estaba maduro para empezar a utilizarlo, empez la revolucin de los objetos; y porque Ada se parece
bastante a Pascal.
Muchos lectores se preguntarn por qu no se ha analizado el lenguaje Ada 95, proviniendo como
proviene de uno de los ms avanzados lenguajes estructurados. La verdad es que a los que agregaron la
orientacin a objetos a un lenguaje tan complejo como Ada 86 no se les ocurri mejor idea que hacerlo mucho
ms complicado an. Los propios creadores de la primera versin de Ada se vieron defraudados con esta nueva
versin. Encima, ni siquiera soporta todos los aspectos del paradigma.
Y el resultado comercial fue todo lo decepcionante que poda esperarse. Ada 95 no ha pasado de ser
un objeto de anlisis acadmicos. As como Ada 83 se adelant mucho a lo que la industria esperaba de un
lenguaje, y luego fracas parcialmente por su carcter revoluciona rio, Ada 95 fracasa por no poder romper con
sus antecedentes procedimentales y por convertir conceptos simples de la orientacin a objetos en
implementaciones tremendamente complicadas.
Herramientas visuales y de desarrollo rpido de aplicaciones
Al hablar de POO no podemos dejar de lado la programacin visual, tambin conocida como
12

Por ejemplo, no debera permitirse sumar una velocidad a un monto en pesos, aunque ambos sean nmeros reales.

- 19 -

CARLOS FONTELA

desarrollo rpido de aplicaciones (RAD es la sigla en ingls). Se entiende por tal a herramientas que permiten
el desarrollo de sistemas sin escribir acciones en un lenguaje de programacin, sino construyendo prototipos de
pantallas y eventos, y utilizando facilidades para acceder a bases de datos y componentes. Esto no solamente
facilita el desarrollo sino que permite una fcil experimentacin con las interfaces de usuario posibles de un
sistema.
A menudo se considera que la aparicin de estos ambientes de programacin (no sera del todo
correcto denominarlos lenguajes), que acompaan el auge de las interfaces de usuario grficas, significan la
partida de defuncin de los lenguajes de programacin.
Sin embargo, pronosticar la desaparicin de los lenguajes de programacin nos parece apresurado.
No se debe dejar de lado el hecho de que todos estos ambientes cuentan con un lenguaje de fondo, el que se
utiliza para desarrollar mdulos que realizan las acciones no visuales (u ocultas) que todo sistema hace.
Es cierto que, con productos RAD, muchas aplicaciones se pueden desarrollar en tiempos muy
cortos, pero se trata de aplicaciones de mucha interfaz de usuario , como pasa en la Web, que tambin tiene sus
herramientas de desarrollo rpido.
Lo que s queda claro es que cada vez se van a utilizar ms estos ambientes que dejarn a cargo del
programador, casi exclusivamente, los mdulos que realizan tareas ocultas. Probablemente, el desarrollo de
interfaces de usuario mediante cdigo escrito a mano cada vez represente una peor inversin del tiempo de
programador.
Esto enfatiza an ms nuestra preocupacin por la programacin modular, especialmente ascendente
y con objetos 13. Al fin y al cabo, los sistemas medianos realizan un gran nmero de tareas que poco tienen que
ver con la interfaz de usuario o los accesos a datos. En estos sistemas, tal vez tenga que haber programadores,
que desarrollen los aspectos ms avanzados de la aplicacin, y lo que se denominan usuarios del ambiente de
desarrollo14 , que se encarguen de la preparacin de interfaces de usuario y accesos a datos. Estos usuarios
podrn tener una formacin ms cercana al desarrollo de interfaces de usuario que al desarrollo de sistemas.
Uno de los problemas con las herramientas RAD es que se busca simplicidad a costa de falta de
originalidad, lo cual puede ser bueno, al reducir el costo de aprendizaje de un nuevo sistema, pero es malo al
desincentivar la creacin de interfaces de usuario orientadas a cada modelo de negocio.
Pero el principal problema que tiene, y que hace que deba plantearse seriamente su solucin, es que
los sistemas desarrollados con herramientas visuales son muy difciles de mantener y de reutilizar. Esta
deficiencia se debe sobre todo a la poca claridad del cdigo. Hay algunas excepciones, no obstante, entre las
cuales destaca la biblioteca Swing para desarrollar aplicaciones de interfaz de usuario grfica en Java 2.
Esta visin a corto plazo de los usuarios de herramientas RAD nos est llevando otra vez a los
lejanos aos anteriores a la primera crisis del software. Hoy por hoy, lo nico que garantiza la modificabilidad
de una aplicacin desarrollada con herramientas RAD es una muy buena documentacin.
13
14

La mayora de estos ambientes maneja POO.


Por ejemplo, usuarios Delphi, usuarios Visual Basic.

- 20 -

PROGRAMACIN ORIENTADA A OBJETOS

3. PROGRAMACIN ORIENTADA A OBJETOS:


GENERALIDADES Y ENCAPSULAMIENTO
OBJETOS Y CLASES
Objetos
Un objeto es toda entidad activa de un programa. Tambin puede decirse que es cualquier cosa, real
o abstracta, de la cual almacenamos datos y la forma de manipular esos datos.
Una analoga con la programacin imperativa nos permitira comparar los objetos a las variables,
aunque no sera del todo exacto.
Un objeto queda definido por las siguientes propiedades:
?? Estado
?? Comportamiento
?? Identidad
El estado de un objeto define la situacin del mismo en un momento establecido en el tiempo. Los
valores que se almacenan de un objeto se llaman generalmente atributos y pueden ser, a su vez, objetos o
variables del lenguaje de programacin que se utilice.
Hay dos tipos de atributos: ol s constantes, que no cambian con el tiempo, y los dinmicos 15 . Por
ejemplo, del estado del objeto libro de programacin, podemos decir, que entre sus atributos constantes estn
el ser de hojas blancas, estar escrito con letras negras, y dems, mientras que como atributo dinmico
podramos decir que est abierto en una pgina en la que se lee el ttulo objetos y clases.
El estado, por lo tanto, viene dado por los valores de todos los atributos del objeto en un momento
dado. Ntese que estos atributos estarn estructurados de una forma tal que establecern lo que llamamos la
estructura interna en los TDA.
El comportamiento es la manera en que un objeto reacciona ante mensajes recibidos, bsicamente
enviando mensajes a otros objetos, respondiendo al que le enva el mensaje o cambiando de estado. Las
distintas formas de respuesta se denominan mtodos , y corresponden a procedimientos y funciones, segn el
lenguaje y su notacin. A priori, para que un objeto le enve un mensaje a otro debera conocerlo, pero hay
soluciones que implementan canales, que permiten que un objeto se comunique con otro conociendo el canal, y
no necesariamente al otro objeto.
De nuevo, tomando el ejemplo de este libro, podemos decir que puede leerse secuencialmente, puede
ser abierto en una pgina en forma directa, puede ser destruido, etc..
En POO, un objeto puede satisfacer solamente ciertos requerimientos, definidos por su interfaz, que
es el conjunto de los mtodos aplicables a ese objeto. Son la propia interfaz y la implementacin de la misma
quienes definen el comportamiento.
La identidad es lo que diferencia a un objeto de todos los otros del mismo tipo. En la programacin
procedimental la analoga lgica es el nombre de variable 16 .
Por ejemplo, este libro que tiene entre sus manos tiene una identidad que lo diferencia de los dems
15
16

Estas definiciones no son estrictas. Hay quienes consideran como estado slo a lo que puede cambiar en el tiempo.
Aunque un objeto puede tener varios, como ocurra con las variables que tenan sinnimos.

- 21 -

CARLOS FONTELA

libros de la misma edicin, an cuando tengan el mismo comportamiento y estado.


Clases
Sin embargo, no puede haber objetos que no respondan a un concepto. Una clase responde a la idea
de concepto, entendido como una nocin compartida que se aplica a determinados objetos en forma consciente.
Para ver si un objeto est comprendido en un concepto se le aplican ciertas pruebas de reconocimiento. Por
ejemplo, para saber si un determinado objeto es un pino, podramos ver si es un rbol, si tiene frutos en forma
de pia, si tiene las hojas cilndricas y alargadas, etc.: si no pasa alguna de las pruebas concluiremos que no es
un pino.
Una clase es un conjunto de objetos con la misma estructura y el mismo comportamiento. Es una
nocin similar a la de tipo en programacin estructurada (de hecho, hay quien habla de tipo de objeto y
reserva el nombre clase para otros usos). Responde a la idea de concepto.
En nuestro ejemplo, se podra hablar de la clase de todos los libros de esta edicin.
La relacin entre objeto y clase se denomina instanciacin . Cada objeto particular es una instancia
de la clase.
Una clase es como un molde desde el que se crean los objetos. De all que casi toda nuestra atencin
como programadores se centre en las clases y no tanto en los objetos.
Dado que todos los objetos de una clase poseen la misma estructura y el mismo comportamiento, la
declaracin de una clase siempre tiene la descripcin de la estructura interna (atributos) y del comportamiento
(mtodos) comunes de la misma.
Ntese la diferencia fundamental entre un objeto y una clase. Un objeto es algo concreto, aunque
pueda ser tanto real como abstracto. Una clase es una abstraccin de un concepto que engloba a todos los
objetos. Por ejemplo, pas, idioma, elefante , libro, taza, auto, son clases, mientras que Bolivia, castellano,
Dumbo, El Quijote de la Mancha, la taza amarilla en que tomo mi desayuno, el auto de patente RRR-222, son
objetos.

ENCAPSULAMIENTO
La abstraccin en programacin orientada a objetos
Todos los lenguajes que soportan POO permiten establecer la abstraccin a nivel de clases,
declarando en su interior tanto la estructura como el comportamiento. Por ejemplo, en Java se definira una
clase para implementar un perodo de tiempo como sigue:
public class cPeriodo {
// atributos o estructura
TFecha desde, hasta;
// mtodos o comportamiento
int cantidadDias () {
// cdigo de la funcin
}
...
}

- 22 -

PROGRAMACIN ORIENTADA A OBJETOS

De esta manera, es fcil crear un TDA, definiendo todo en un mismo bloque de cdigo 17.
El ocultamiento en programacin orientada a objetos
Todos los lenguajes que soportan POO tienen, por lo menos, dos categoras de acceso de atributos y
mtodos, denominadas pblico y privado. Como vimos, lo conveniente es que los mtodos sean de acceso
pblico y los atributos privados.
Por ejemplo, en Java se declarara:
class cPeriodo {
// atributos inaccesibles desde fuera:
private TFecha desde, hasta;
// mtodo visible desde otras clases:
public int cantidadDias () {
// cdigo de la funcin
}
...
}

Como dijimos antes, no podemos pretender hacer un genuino ocultamiento si no proveemos al cliente
de toda la funcionalidad que puede llegar a necesitar.
Esto est relacionado con la nocin de atributo conceptual, que es todo aquello que un usuario
presuma que debe existir como atributo, aun cuando no exista explcitamente. Por ejemplo, un nmero
complejo se puede implementar con dos atributos que representen el mdulo y el argumento, pero las partes
real e imaginaria, aunque no sean atributos fsicos, son atributos conceptuales, pues todo cliente presumir que
existen. A menudo estos atributos son llamados propiedades.
En consecuencia, para garantizar el ocultamiento de la informacin, todo atributo conceptual debe
tener un mtodo selector para obtener su valor y un mtodo modificador para alterarlo.
Encapsulamiento
En POO, a la conjuncin de abstraccin y ocultamiento de implementacin se la llama
encapsulamiento .
Segn Booch [6], encapsulamiento es el proceso de almacenar en un mismo compartimiento los
elementos de una abstraccin que constituyen su estructura y su comportamiento; sirve para separar la interfaz
contractual de una abstraccin y su implantacin.

TIPOS ESPECIALES DE ATRIBUTOS


En este tem vamos a analizar algunos tipos de atributos que tienen un inters particular:
?? De clase.
?? Con valor constante.
?? Con restricciones.
Atributos de clase
Se denominan atributos de clase aquellos que tienen el mismo valor para cada objeto de la clase. A
los atributos que no son de clase se los suele llamar atributos de instancia.
17

Esto es ms cierto en Java que en Object Pascal, donde slo se declaran los encabezados de los mtodos. En C++ se puede hacer de
las dos maneras.

- 23 -

CARLOS FONTELA

Por ejemplo, en una aplicacin con ventanas, si las modificaciones de color deben afectar
simultneamente a todas las ventanas, el atributo Color sera un atributo de clase. En este caso se tratara de un
atributo de clase cuyo valor puede variar, pero cuando vara lo hace para todas las instancias de la clase a la
vez.
Otro ejemplo podra ser declarar la clase de los nmeros reales, como derivada de los complejos,
pero con parte imaginaria igual a cero. En este caso se tratara de un atributo de clase constante.
A veces se los llama atributos estticos.
Atributos con valor constante
A veces ocurre que en una clase un determinado atributo debe tener siempre el mismo valor.
Por ejemplo, en una aplicacin comercial, un identificador de cliente, que no se modifica mientras
exista el cliente. En este caso se trata de un atributo constante que es distinto para cada instancia.
Otro ejemplo podra ser el que definimos anteriormente de los reales y los complejos. En este caso
sera adems un atributo de clase.
Atributos con restricciones
A veces algunos atributos tienen que cumplir una restriccin en su valor. La restriccin puede ser
absoluta o estar vinculada a otro atributo. Estas condiciones que deben cumplir los atributos suelen llamarse
invariantes.
Por ejemplo, una restriccin absoluta sera imponer que un atributo que contiene un monto sea
siempre positivo.
Un ejemplo de restriccin vinculada a otro atributo se podra dar si, por razones especiales, se
decidiera implementar una clase que almacene un perodo, guardando simultneamente la fecha de inicio, la de
finalizacin y la duracin.
Siempre que haya restricciones sobre atributos, hay que verificar el cumplimiento de la restriccin en
todas las operaciones de modificacin, incluyendo el constructor. Una posibilidad interesante es encapsular los
atributos que tienen restricciones interrelacionadas en una clase aparte.
Mtodos de clase
Un concepto un poco menos til que el del atributo de clase es el de mtodo de clase. Se define as
al mtodo que no puede acceder a atributos de instancia y del cual existe una sola versin posible para toda la
clase.
Tambin se utilizan mtodos de clase cuando se pretende usar POO estricta (sin variables que no
sean objetos ni subprogramas que no sean mtodos), pero a la vez se desea llamar un mtodo (subprograma) sin
usar un objeto.
En realidad, con los mtodos de clase se estn utilizando subprogramas en forma global. Por eso, si
vemos muchos mtodos de clase en un sistema, tal vez no estemos haciendo un autntico desarrollo orientado a
objetos.
A veces de los llama mtodos estticos.

TERMINOLOGA DE OBJETOS
Cada vez que surge una nueva tecnologa, son muy raros los casos en que sus primeros impulsores se
resisten a la tentacin de crear toda una gama de nuevos trminos relacionados con ella. As, de la mano de la
programacin estructurada, por ejemplo, el trmino accin reemplaz al trmino sentencia ; procedimiento
reemplaz a subrutina. La tecnologa de objetos por cierto no es una excepcin.
Por supuesto que esto tiene su razn de ser: los trminos accin y sentencia , por ejemplo, si bien
evocan conceptos parecidos, no significan lo mismo. Adems, utilizar una nueva terminologa facilita el

- 24 -

PROGRAMACIN ORIENTADA A OBJETOS

cambio en la manera de pensar.


Cuando se trabaja con objetos, los datos elementales de un objeto o clase se denominan atributos.
El cdigo para trabajar con un objeto es el comportamiento (en programacin tradicional
hablaramos de funcionalidad) de ese objeto.
El comportamiento del objeto se define en base a sus mtodos 18 .
Un tipo de objetos se denomina clase , y a las variables de esa clase se las denomina objetos o
instancias de la clase.
A las invocaciones a los mtodos se las llama mensajes o solicitudes. Un mensaje es una
comunicacin que un objeto enva a otro con la expectativa de desencadenar una actividad.
El ocultamiento de la informacin cuando se implementan tipos abstractos de datos, adems de poner
juntos los atributos y sus mtodos, se denomina encapsulamiento.

ESTADOS, EVENTOS Y TRANSICIONES


El estado de un objeto est representado por el conjunto de valores adoptado por los atributos y
vnculos de un objeto en un momento dado. Podemos generalizar este concepto diciendo que es una situacin
de un objeto durante la cual satisface una condicin, realiza una actividad o espera un evento.
Los cambios de estado que sufren los objetos se deben a estmulos o mensajes recibidos de otros
objetos, cuyos efectos generalmente llamamos eventos.
Un evento indica la aparicin de un estmulo que puede disparar una transicin de estados. Es la
especificacin de un acontecimiento significativo, como una seal recibida, un cambio de estado o el simple
paso de un intervalo de tiempo. Los eventos pueden ser internos o externos al sistema.
Los eventos pueden ser asncronos, cuando el emisor de la seal puede seguir trabajando sin esperar
una respuesta, o sncronos, si debe quedarse esperando la respuesta del receptor. Por ejemplo, las seales son
asncronas y las llamadas a mtodos son sncronas.
En captulos posteriores analizaremos nuevamente el concepto de evento.
Una transicin entre dos estados indica que un objeto que est en un primer estado realizar ciertas
acciones y entrar en un segundo estado cuando ocurra algn evento especificado y se satisfagan ciertas
condiciones.

OPERACIONES
Estado observable de un objeto
Las operaciones que se aplican a un objeto o clase, se pueden clasificar en operaciones de consulta ,
que son los mtodos que no alteran el estado de un objeto, y las de modificacin , que son las que s pueden
alterar el estado de un objeto.
Se llama estado observable al resultado de la aplicacin de todas las operaciones de consulta. Puede
no coincidir con el estado real cuando algunos atributos no sean accesibles mediante operaciones de consulta o
cuando las operaciones de consulta permitan definir otros atributos conceptuales.
18

Hay bibliografa que distingue los conceptos de mtodo y operacin, dejando el primero para la implementacin de una operacin, y
define a la operacin como un servicio que se puede requerir de cualquier objeto de una clase.

- 25 -

CARLOS FONTELA

Pasaje por valor y por referencia en programacin orientada a objetos


En la programacin procedimental es usual, cuando se trabaja con subprogramas con parmetros,
hablar de variables que se pasan por valor, de las que no se desea que su estado se modifique en el
subprograma, y otras que se pasan por referencia, que van a ser modificadas en el mismo.
Esto no debiera ser as en POO. La idea de los mtodos de la POO es que slo debieran cambiar el
estado del objeto para el cual est siendo llamado el mtodo. Si se intenta modificar el estado de otro objeto se
dice que estamos introduciendo efectos colaterales, lo cual a veces se hace, aunque deben tomarse los
siguientes recaudos:
?? Analizar si tiene sentido
?? Analizar si esto queda claro para el usuario
?? Analizar si es probable que cause problemas
En todo otro caso, los efectos colaterales deben evitarse.
De todas maneras, en los lenguajes que trabajan con un modelo de memoria con referencias es
imposible evitar el pasaje por referencia.
Constructores
Los constructores son mtodos especiales que efectan tareas de inicializacin oculta y necesaria.
Por lo tanto, antes de usar un objeto se debe invocar a su constructor. Sin embargo, no todos los compiladores
de lenguajes verifican esta condicin, quedando en estos casos a cargo del programador.
Como consecuencia de lo anterior, cada clase debe tener un constructor. En Java y en C++ siempre
hay un constructor con el nombre de la clase, aunque se lo puede redefinir con constructores definidos por el
programador. En Object Pascal, en cambio, todo queda a cargo del programador.
Dado que el constructor es lo primero que se invoca para cada objeto, es una prctica comn y
recomendable usarlos para inicializar valores de los atributos.
En cuanto a la invocacin de los constructores, se suelen cometer dos errores comunes: invocarlo
ms de una vez o no invocarlo nunca. Por eso, conviene invocarlo al principio del bloque de cdigo en el que
fue declarado el objeto. Esta recomendacin la hacemos para Object Pascal, pues en Java y C++ el constructor
se invoca automticamente cuando se crea la instancia.
Destructores
Los destructores son mtodos que cumplen tareas de liberacin de memoria y vnculos con otros
objetos.
Sin embargo, no es un concepto que exista en todos los lenguajes. En Java, por ejemplo, no hay
destructores debido a que tiene un mecanismo de recoleccin automtica de basura.
En los lenguajes en los que no se hace recoleccin de basura, es conveniente llamar al destructor de
la clase al final de la vida de un objeto, chequeando no invocarlo ms de una vez. Una buena posibilidad es
llamar al destructor al final del bloque de cdigo en el que fue declarado, aunque no siempre es posible o
recomendable.
Sobrecarga
La mayora de los lenguajes de POO permiten que un subprograma tenga el mismo nombre que
otros, con la condicin de que tengan distinta cantidad de parmetros o stos sean de tipos distintos. Es una
propiedad que permite definir diferentes implementaciones para la misma operacin. Este concepto se
denomina sobrecarga.
En Java, en donde los subprogramas slo pueden definirse como mtodos dentro de una clase, se
podr escribir:

- 26 -

PROGRAMACIN ORIENTADA A OBJETOS

class cElipse {
void cElipse () {
// cuerpo de cElipse, sin parmetros
}
void cElipse (int Radio1, int Radio2) {
// cuerpo de cElipse, con 2 parmetros enteros
}
void cElipse (double Radio1, double Radio2) {
// cuerpo de cElipse, con 2 parmetros double
}
// int cElipse ()
// sera invlido porque difiere slo en el tipo devuelto
// otras definiciones de atributos y mtodos
}

En este caso hemos sobrecargado el constructor de cElipse, pero puede hacerse con cualquier mtodo
de la clase.
Pero incluso en C++ y Object Pascal est permitida la sobrecarga, y aun en subprogramas declarados
fuera de una clase. Por ejemplo, los siguientes encabezados de funciones son vlidas en Object Pascal en forma
simultnea:
function Potencia (X: Real; N: Integer) : Real; overload;
function Potencia (M: Integer; N:Integer) : Integer; overload;
function Potencia (X: Real; Y: Real) : Real; overload;

Sin embargo, sera incorrecto declarar:


function Potencia (M: Integer; N:Integer) : Real; overload;
{ incorrecto: difiere slo en el tipo del resultado }

Ntese que en Object Pascal es necesario poner la palabra overload, cosa que no existe en C++ y
Java.
En C++ est permitido sobrecargar operadores, una idea tomada de Ada. Al fin y al cabo, los
operadores son funciones (en la suma de enteros, + es una funcin entera de dos parmetros enteros). Por
ejemplo, en la implementacin de complejos anterior se podra haber substituido la funcin Suma por una
sobrecarga al operador + de esta forma:
cComplejo cComplejo :: operator+ (cComplejo v)
{

cComplejo aux;
aux.re = re + v.re;
aux.im = im + v.im;
return aux;

La funcin anterior se puede invocar, por ejemplo:


cComplejo z, u, w;
...
w = z + u;

Los operadores sobrecargados se heredan a las clases descendientes, salvo el operador de asignacin
y los de asignacin de memoria new y delete. Hay algunas propiedades interesantes, como que el operador de
desigualdad no se puede sobrecargar, sino que devuelve lo contrario del operador de igualdad.

- 27 -

CARLOS FONTELA

Se ha hablado muy mal de la sobrecarga de operadores en C++, de lo poco til que resulta y de los
problemas que acarrea. Sin embargo, bien usados pueden aclarar bastante el uso de determinadas funciones.
Incluso los operadores de asignacin, de igualdad y desigualdad y los de comparaci n se podran sobrecargar
siempre para darles el significado que deberan tener en cada clase. As hicimos nosotros en los ejercicios
resueltos en C++. Lo que ocurre es que muchos programadores han usado los operadores para cualquier cosa,
bastardeando el sentido original de los mismos. Por eso, cuando se trabaja con sobrecarga de operadores, ms
an que con sobrecarga de funciones en general, debe respetarse la semntica del operador original.

IMPLEMENTACIN DE OBJETOS Y CLASES EN DI STINTOS LENGUAJES


Objetos y clases en Object Pascal
En Object Pascal, un objeto se declara en la declaracin de variables y una clase en la de tipos.
Por ejemplo, la siguiente declaracin introduce un objeto Z como instancia de la clase cComplejo:
var Z : cComplejo;

Y esta otra introduce la clase cComplejo:


type cComplejo = class
private
Re, Im : Real;
public
constructor Create (R,I: Real);
procedure Suma (X,Y: cComplejo);
procedure Resta (X,Y: cComplejo);
function Modulo : Real;
function Argumento : Real;
function ParteReal : Real;
{ ... ms operaciones ... }
end;

En realidad, el fragmento anterior slo declara la clase, pero la implementacin debe definirse
luego 19 :
{ ... implementaciones anteriores ... }
procedure cComplejo.Resta (X,Y: cComplejo);
begin
Re := X.Re Y.Re; Im := X.Im Y.Im
end;
function cComplejo.Modulo : Real;
begin
Modulo := Sqrt(Re*Re+Im*Im)
end;
{ ... continan las implementaciones ... }

El cliente de la implementacin de cComplejo escribir acciones como:


Z.Sumar(V,W);

{ Z, V y W deben ser instancias de cComplejo }

19

Si estamos trabajando en una unidad de biblioteca, la declaracin se suele poner en la parte interface y la implementacin debe
definirse en la implementation.

- 28 -

PROGRAMACIN ORIENTADA A OBJETOS

X := Z.Modulo; { Z es una instancia de cComplejo y X un Real }

Hay varias cosas que se pueden destacar aqu:


?? La declaracin de clases debe hacerse con la palabra class para asegurar el modelo de
memoria que luego se describir. Versiones anteriores de Object Pascal usaban la palabra
object, que se mantiene por compatibilidad hacia atrs, pero no se recomienda.
?? Los atributos y mtodos privados son visibles, no slo dentro de la clase en la cual estn
declarados, sino en todo el archivo en el cual se los declar (programa o unidad de biblioteca).
?? La declaracin hecha con las palabras public o private afecta a todos los atributos y mtodos
que le siguen, hasta que aparezca una directiva en contrario.
?? Para acceder a un atributo se hace con el nombre del objeto seguido de punto y el nombre del
atributo, como con las variables compuestas (record) de Pascal.
?? Los mtodos hacen uso de un parmetro adicional a los que figuran en su encabezado. Este
parmetro se denomina Self y el cuerpo de cada mtodo est enmarcado por un with Self do
implcito. Es por eso que en cada mtodo de los de arriba es como si faltase un parmetro, y es
por el with implcito que podemos colocar directamente los nombres de los atributos Re e Im
sin poner Self. delante.
?? El parmetro Self es una referencia a un objeto instancia de la clase en cuestin. Por el
momento, podramos decir que es un parmetro por referencia.
?? En las llamadas a mtodos el argumento que corresponde a Self se pone por delante del
nombre del mtodo. En este sentido, Self es una referencia al objeto para el cual se est
llamando al mtodo.
?? Los constructores y destructores pueden tener cualquier nombre que desee el programador,
aunque por cuestiones que analizaremos ms adelante conviene que se llamen Create y
Destroy.
La llamada a un constructor no se hace de la forma habitual que tiene Pascal para llamar
procedimientos. Por ejemplo, en el caso anterior se llamara as al constructor:
Z := cComplejo.Create(2,3);

Un mtodo de clase se puede indicar en Object Pascal anteponindole la palabra class en su


declaracin. Los atributos de clase no estn soportados en Object Pascal, debiendo simularse con mtodos de
clase y variables declaradas en la parte de implementacin.
Object Pascal no implementa atributos con valor constante, por lo que el programador debe
garantizar la constancia mediante la inicializacin en el constructor y sin proveer forma de alterarlos con
ningn otro mtodo.
Los atributos con restricciones no estn implementados, por lo que debe hacerlo el programador,
asegurando que tanto el constructor como todos los mtodos modificadores no puedan alterar la restriccin.
En Object Pascal existe el concepto de propiedad, que permite mejorar el encapsulamiento. Por
ejemplo, en el caso de los complejos se podra definir una propiedad PReal:
property PReal:Real read Re write AsignarReal;

donde el mtodo AsignarReal se debera definir:


procedure cComplejo.AsignarReal (PR:Real);
begin
Re := PR
end;

De aqu en ms se podra utilizar directamente la propiedad PReal, como:

- 29 -

CARLOS FONTELA

Z.PReal := 4; { llama a Z.AsignarReal(4)


}
X := Z.PReal; { obtiene directamente el valor del atributo Z.Re }

Obviamente, esta herramienta sirve tambin para definir propiedades que no estn directamente
atadas a un atributo. O, lo que es lo mismo, podran usarse para definir atributos conceptuales. Ntese que si
implementamos la clase cComplejo con un par de valores para sus partes real e imaginaria, podramos definir
propiedades para el mdulo y el argumento, en este caso como de slo lectura:
property PModulo:Real read Modulo;
property PArgumento:Real read Argumento;

Es en este sentido que decimos que sirve para mejorar el encapsulamiento. Pero no debieran usarse
las propiedades para eludir el encapsulamiento.
Las propiedades pueden tener un valor por defecto, pero no si son de slo lectura.
De todas maneras, por ser una capacidad exclusiva de Object Pascal y alguno que otro lenguaje 20 , no
entraremos en detalle.
Objetos y clases en C++
En C++ un objeto se declara como si fuera una variable, y una clase con la palabra reservada class.
Por ejemplo, el siguiente fragmento declara z como instancia de cComplejo, a la vez que llama al
constructor cComplejo pasndole como argumentos 2 y 3:
cComplejo z (2,3);

Y la declaracin que sigue sera la de la clase cComplejo:


class cComplejo
{ private:
double re, im;
public:
cComplejo (double x, double y); // constructor
~cComplejo;
// destructor
void suma (cComplejo x, cComplejo y);
void resta (cComplejo x, cComplejo y);
double modulo();
double argumento();
double parteReal();
// ... ms operaciones ...
} ;

Ntese que en la declaracin de la clase no se suelen poner las implementaciones de los mtodos, que
se definen luego (aunque nada impide implementarlos en la propia declaracin, al estilo Java), como en el
ejemplo que sigue:
// ... implementaciones anteriores ...
void cComplejo :: resta (cComplejo x, cComplejo y);
{
re = x.re - y.re; im = x.im - y.im;
}
void cComplejo :: modulo()
{
return sqrt(re*re+im*im)
// presumimos la existencia de la funcin sqrt
}
20

Como C#.

- 30 -

PROGRAMACIN ORIENTADA A OBJETOS

// ... continan las implementaciones ...

El cliente de la implementacin de cComplejo escribir acciones como:


z.sumar(v,w);
x = z.modulo();

{ z, v y w deben ser instancias de cComplejo }


{ z es una instancia de cComplejo y x un double }

Hay varias cosas que se pueden destacar aqu:


?? Los atributos y mtodos privados son visibles slo dentro de la clase en la cual estn
declarados.
?? La declaracin hecha con las palabras public o private afecta a todos los atributos y mtodos
que le siguen, hasta que aparezca una directiva en contrario.
?? Para acceder a un atributo se hace con el nombre del objeto seguido de punto y el nombre del
atributo, como con las variables compuestas (struct) de C.
?? Los mtodos hacen uso de un parmetro adicional a los que figuran en su encabezado, que es
un puntero. Este puntero se denomina this y apunta a un objeto instancia de la clase en
cuestin. En el cuerpo de cada mtodo, cuando se invoca un mtodo o se hace uso de un
atributo sin especificar la instancia se refiere a *this. Es por eso que en cada mtodo de los de
arriba es como si faltase un parmetro y podemos colocar directamente los nombres de los
atributos re e im sin poner this-> delante.
?? En las llamadas a mtodos el argumento que corresponde a this se pone por delante del
nombre del mtodo. En este sentido, this es un puntero al objeto para el cual se est llamando
al mtodo.
?? Los constructores llevan el mismo nombre de la clase. Si no se declara ninguno, est definido
un constructor por omisin, sin parmetros.
?? Los destructores llevan el mismo nombre de la clase precedidos por el carcter ~. Si no se
declara ninguno, est definido un constructor por omisin, sin parmetros. El destructor es
siempre invocado automticamente cuando el programa sale del mbito en el cual es declarado
un objeto.
Se pueden declarar algunos mtodos como funciones en lnea mediante la directiva inline. Una
funcin de lnea es aqulla que el compilador expande en el punto donde es llamada en lugar de ser realmente
llamada. Es decir, no se genera un cdigo separado para la funcin de lnea, sino su cdigo se copia en cada
lugar en que la funcin es invocada21 . Su ventaja es que la invocacin se hace ms velozmente, debido a que se
eliminan los tiempos de vinculacin entre mdulos y se ahorran prlogos y eplogos de la funcin compilada
aparte que en el caso de funciones pequeas podran ser ms largos que el cuerpo de la propia funcin. Como
desventaja, si la funcin de lnea es invocada varias veces en un programa, se la copia tantas veces como es
llamada, por lo que aumenta el tamao del cdigo que sera necesario si fuera una funcin corriente. Como
corolario, debe tratarse que las funciones de lnea sean las ms cortas de un programa y que se invoquen pocas
veces.
Se puede hacer que una funcin que no es un mtodo miembro de una clase tenga acceso a la parte
privada de la misma, declarndola amiga22 de la clase. Por ejemplo:
class c
{

private:
int x;
public:
c();

21
22

En realidad, la definicin de una funcin en lnea deja en manos del compilador si la expande o no, en base, por ejemplo, a su tamao.
A veces se las llama funciones de ayuda.

- 31 -

CARLOS FONTELA

~c();
friend int a (void);
}

En el caso anterior, la funcin a es amiga de la clase c y puede acceder al atributo x. Sin embargo, a
no es un mtodo miembro de c, y slo se est escribiendo un prototipo de a en la declaracin de c. La funcin a
se declarar ms adelante como cualquier funcin de C o C++.
Puede parecer algo intil la posibilidad de declarar funciones amigas. Sin embargo, pueden utilizarse
cuando se desea que una funcin acceda a atributos privados de ms de una clase. En este caso se la declara
amiga de ambas y se habr solucionado el problema.
C++ permite la definicin de clases internas a otras clases. Una clase interna puede utilizar mtodos
y atributos privados de su clase externa, con la cual no guarda ninguna relacin de herencia (veremos herencia
en el prximo captulo). Esto permite vincular clases muy acopladas, de modo de facilitar el desarrollo y
mantenimiento de las mismas. Esta propiedad no la utilizaremos en este curso.
Un atributo de clase (o esttico) se indica en C++ anteponindole la palabra static en su declaracin.
Tambin pueden declararse del mismo modo mtodos de clase (o esttico).
Un atributo con valor constante se indica ponindole la palabra const en su declaracin, a
continuacin del nombre.
Los atributos con restricciones no estn implementados en C++, por lo que debe hacerlo el
programador, asegurando que tanto el constructor como todos los mtodos modificadores no puedan alterar la
restriccin.
A continuacin se muestran una declaracin de un mtodo y un atributo de clase, un atributo con
valor constante y un atributo con valor por defecto:
class cVentanaEspecial
{

static int color;

// atributo de clase

static int getColor(); // mtodo de clase


const int limiteIzquierdo = 0; // atributo con valor constante
int limiteSuperior = 0;
// atributo con valor por defecto
}

En C++ hay tambin formas de especificar objetos constantes cuyo estado no puede variar y
mtodos que no pueden modificar el estado de un objeto, siempre usando la palabra const.
Objetos y clases en Java
En Java un objeto se declara como si fuera una variable, y una clase con la palabra reservada class .
Por ejemplo, el siguiente fragmento declara z como instancia de cComplejo, a la vez que llama al
constructor cComplejo pasndole como argumentos 2 y 3:
cComplejo z = new cComplejo(2,3);

Y la declaracin que sigue sera la de la clase cComplejo:


public class cComplejo
{

private double re, im;


public cComplejo (double x, double y) { // constructor
re = x; im = y;
}
public void suma (cComplejo x, cComplejo y) {
re = x.re + y.re;
im = x.im + y.im;

- 32 -

PROGRAMACIN ORIENTADA A OBJETOS

}
public void resta (cComplejo x, cComplejo y) {
re = x.re y.re;
im = x.im y.im;
}
public double modulo() {
return Math.sqrt(re*re+im*im)
}
// ... ms operaciones ...
} ;

Ntese que en la definicin de la clase se ponen tambin las implementaciones de los mtodos. Dicho
de otro modo, se hacen en el mismo lugar la declaracin y la definicin de los mtodos de la clase.
El cliente de la implementacin de cComplejo escribir acciones como:
z.sumar(v,w); { z, v y w deben ser instancias de cComplejo }
x = z.modulo();

{ z es una instancia de cComplejo y x un double }

Hay varias cosas que se pueden destacar aqu:


?? Los atributos y mtodos privados son visibles slo dentro de la clase en la cual estn definidos.
?? La declaracin hecha con las palabras public o private afecta slo al atributo o mtodo que le
sigue.
?? Si a un atributo o mtodo no se le especifica la visibilidad, sta es la que Java adopta por
omisin, conocida como friendly, que implica que ese atributo o mtodo es visible para sus
descendientes y dentro del paquete 23 en que est incluida la clase, pero privado para cualquier
clase fuera del paquete.
?? Las clases tambin tienen visibilidad (pblicas o friendly , nicamente). Una clase pblica va a
ser accesible desde fuera para instanciarla, mientras una friendly slo va a poder accederse
desde las clases del mismo paquete. Slo puede haber una clase pblica por archivo fuente y
debe tener exactamente el mismo nombre del archivo 24 . No hay clases privadas, pero si no
quiero que una clase pueda instanciarse desde fuera de mi cdigo fuente, puedo hacer privado
su constructor.
?? Para acceder a un atributo se hace con el nombre del objeto seguido de punto y el nombre del
atributo, como con las variables compuestas (struct/record) de C y Pascal.
?? Los mtodos hacen uso de un parmetro adicional a los que figuran en su encabezado, que es
una referencia a un objeto instancia de la clase en cuestin, llamada this. En el cuerpo de cada
mtodo, cuando se invoca un mtodo o se hace uso de un atributo sin especificar la instancia
se refiere a this. Es por eso que en cada mtodo de los de arriba es como si faltase un
parmetro y podemos colocar directamente los nombres de los atributos re e im sin poner this.
delante.
?? En las llamadas a mtodos el argumento que corresponde a this se pone por delante del
nombre del mtodo. En este sentido, this es una referencia al objeto para el cual se est
llamando al mtodo.
?? Los constructores llevan el mismo nombre de la clase. Si no se declara ninguno, est definido
un constructor por omisin, sin parmetros. Pero si se declara algn constructor con
parmetros, deja de existir el constructor sin parmetros.
23

El concepto de paquete se estudiar ms adelante. Podemos adelantarnos diciendo que es una forma de agrupar una biblioteca de
clases en Java. El concepto de clase descendiente se ve en el captulo prximo.
24
Si la clase se llama cComplejo, el archivo ser cComplejo.java, respetando maysculas y minsculas.

- 33 -

CARLOS FONTELA

?? No hay destructores.
Java permite la definicin de clases internas a otras clases, con diversos grados de visibilidad. Incluso
se pueden definir clases locales a un mtodo y clases annimas. Una clase interna puede incluso utilizar
mtodos y atributos privados de su clase externa, con la cual no guarda ninguna relacin de herencia (veremos
herencia en el prximo captulo). Esto permite vincular clases muy acopladas, de modo de facilitar el desarrollo
y mantenimiento de las mismas. Esta propiedad no la utilizaremos en este curso.
Un atributo de clase (o esttico) se indica en Java anteponindole la palabra static en su declaracin.
Tambin pueden declararse del mismo modo mtodos de clase (o esttico).
Un atributo con valor constante se define anteponindole la palabra final en su declaracin, pero slo
si no es un objeto. Estas constantes se pueden inicializar con valores obtenidos en tiempo de ejecucin. En caso
de ser un objeto, lo que se creara sera una referencia constante, por lo que no nos sirve, y ser el programador
quien deber implementar el atributo constante en el constructor y asegurarse de que ningn otro mtodo lo
modifique. Combiando las directivas static y final declaramos constantes globales.
Los atributos con restricciones no estn implementados en Java, por lo que debe hacerlo el
programador, asegurando que tanto el constructor como todos los mtodos modificadores no puedan alterar la
restriccin.
A continuacin se muestran una declaracin de un mtodo y un atributo de clase, un atributo con
valor constante y un atributo con valor por defecto:
class cVentanaEspecial
{

static int color;


// atributo de clase
static int getColor(); // mtodo de clase
final int limiteIzquierdo = 0; // atributo con valor constante
// funciona slo si el atributo no es un objeto
int limiteSuperior = 0;
// atributo con valor por defecto

EJERCICIO RESUELTO: IMPLEMENTACIN DE NMEROS RACIONALES


Enunciado
Escribir una clase que implemente el TDA cRacional, que maneje nmeros racionales de modo tal de
poder hacer las siguientes operaciones: creacin en base al numerador y denominador, igualdad, suma, resta,
producto, cociente, conversin a real y simplificacin.
Solucin en Object Pascal
Ver apndice A: Implementacin de nmeros racionales
Solucin en C++
Ver apndice B: Implementacin de nmeros racionales
Solucin en Java
Ver apndice C: Implementacin de nmeros racionales

- 34 -

PROGRAMACIN ORIENTADA A OBJETOS

EJERCICIO RESUELTO: IMPLEMENTACIN DE CONJUNTOS


Enunciado
Escribir una clase para implementar conjuntos de enteros de valores desde 0 hasta 5000 utilizando
arreglos de elementos lgicos.
Solucin en Object Pascal
Ver apndice A: Implementacin de conjuntos
Solucin en C++
Ver apndice B: Implementacin de conjuntos
Solucin en Java
Ver apndice C: Implementacin de conjuntos

- 35 -

CARLOS FONTELA

4. PROGRAMACIN ORIENTADA A OBJETOS:


REUTILIZACIN Y EXTENSIN DEL CDIGO
Llamamos reutilizacin al uso de clases u objetos desarrollados y probados en un determinado
contexto, para incorporar esa funcionalidad en una aplicacin diferente a la de origen. En este sentido, el uso de
TDA bien definidos ya constituye reutilizacin del cdigo.
La extensin se basa en aprovechar las clases desarrolladas para una aplicacin, utilizndolas en la
construccin de nuevas clases para la misma u otra aplicacin.
De todos modos, como la extensin es una forma de reutilizacin usando una acepcin ms amplia
del trmino, se suelen englobar bajo el concepto comn de reutilizacin. As haremos nosotros.

REUTILIZACIN CON COMPOSICIN


Composicin
La forma ms simple de reutilizar una clase es simplemente haciendo una nueva clase que la
contenga. Esta es una tcnica llamada composicin, anterior a la POO, como se muestra en el ejemplo que
sigue en Pascal:
type cFigura = record
{ declaracin de una figura }
end;
type cVectorFiguras = record
V : array [1..100] of cFigura;
CantFiguras : Word
end;

Ntese que estamos declarando un arreglo compuesto por figuras, de modo tal que si eliminamos el
arreglo eliminamos las figuras. Decimos que las figuras son los objetos (o variables) contenidos y el arreglo el
objeto (o variable) contenedor. Bsicamente, entre contenedor y contenido hay una relacin del tipo
contiene: un vector de figuras contie ne figuras.
La ventaja obvia de usar composicin con POO es el encapsulamiento, que nos permite no slo
declarar la estructura de los datos sino tambin las operaciones sobre los mismos. Eso se muestra en el ejemplo
siguiente:
type cFigura = class
private
{ aqu van los atributos de una figura }
public
{ aqu van constructor y destructor }
procedure Mover (X,Y:Word);
procedure Dibujar;
{ siguen ms mtodos de cFigura }
end;
type cVectorFiguras = class
private
V : array of cFigura;

- 36 -

PROGRAMACIN ORIENTADA A OBJETOS

CantFiguras : Word;
public
{ aqu van constructor y destructor }
procedure DibujarTodas;
{ dibuja todas las figuras del vector }
{ siguen ms mtodos de cVectorFiguras }
end;

Agregacin
Hay agregacin cuando una clase cumple un factor preponderante sobre otra clase. Por ejemplo, la
clase "empresa" sobre la clase "persona" (ntese que la eliminacin de la empresa no implica la eliminacin de
las personas). Es un concepto poco til, pues es una simple asociacin.
Sin embargo, muchas veces esta asociacin se representa guardando un puntero en la clase
preponderante, lo cual implica una composicin a nivel del puntero. Esto es todava ms visible en los
lenguajes en los que se representan los objetos como referencias, como Java.
El ejemplo del arreglo de figuras tambin podra haberse implementado como una simple agregacin,
si permitimos que las figuras individuales sobrevivan a la muerte del arreglo que las agrupa.
La composicin es, en realidad, un caso particular de agregacin.

REUTILIZACIN CON HERENCIA


Definicin y ejemplos
La herencia es algo central en la POO. Adems, es la propiedad de la POO que ms colabora para
lograr una alta reutilizacin del cdigo.
Por la herencia, cada clase puede tener una clase ancestro y clases descendientes. Y tambin gracias
a ella, cada clase hereda atributos y comportamiento de su clase ancestro. La idea es que haya familias de clases
que compartan estructuras y comportamientos similares.
La herencia parte de relaciones del tipo "es un", las mismas que se utilizan para todas las taxonomas
de las ciencias. Por ejemplo, en Zoologa, las orcas y los caballos son mamferos, por lo que podramos decir
que heredan, de la clase ancestro de los mamferos, atributos (poseen mamas, sangre, etc.) y comportamiento
(gestan hijos en su seno, los amamantan en los primeros das de vida, etc.). Lo mismo podramos decir en
Matemtica de los enteros y reales como subclases de nmeros. Insisto, esto es factible por la relacin "es un":
una orca es un mamfero, un real es un nmero.
Veamos algunos ejemplos de taxonomas usuales provenientes de distintas ciencias:

- 37 -

CARLOS FONTELA

Taxonoma de animales
cAnimal

cVertebrado

cMamifero

cElefante

cInvertebrado

cAve

cPez

cMurcielago

cMolusco

cCaracol

cCrustaceo

cCalamar

Taxonoma de idiomas
cIdioma

cMonosilabico

cAglutinante

cLatino

cIndoeuropeo

cGermanico

cSemitico

cEslavo

cIndoiranio

Taxonoma de nmeros
cComplejo

cReal

cRacional

cEntero

cEnteroNegativo

cImaginario

cIrracional

cFraccionario

cNatural

- 38 -

PROGRAMACIN ORIENTADA A OBJETOS

Taxonoma de figuras
cFigura

cElipse

cCuadrilatero

cCircunferencia

cParalelogramo

cRectangulo

cTrapecio

cRectangulo

cTriangulo

cOtras

cAcutangulo

cObtusangulo

cRombo

cCuadrado

De un anlisis de las figuras anteriores, podemos deducir:


?? Las clasificaciones no tienen por qu ser completas, pero s excluyentes.
?? Algunas de las clases del rbol pueden no tener instancias: son llamadas clases abstractas (las
veremos en el prximo captulo).
?? La ubicacin de una clase en la jerarqua se establece por la relacin es un.
?? Cada clase hereda comportamiento y estructura de su ancestro.
Utilizacin de herencia
Ante todo, digamos que no se debe confundir herencia con instanciacin, pues la primera es una
relacin entre clases y la segunda entre una clase y un objeto de la misma. Tampoco debe confundirse con la
composicin: en un caso se trata de una relacin contiene y en el otro de una relacin es un.
En cualquier lenguaje de programacin que soporte POO, cuando se declara una clase descendiente
se entiende que esta clase hereda de su ancestro inmediato todos sus atributos y todos sus mtodos, en forma
implcita. Adicionalmente, la clase hija puede agregar atributos y mtodos propios, que a su vez sern
heredados por sus descendientes junto con lo que ella hered de sus ancestros.
Por ejemplo, tomando el caso de las figuras geomtricas ya mostrado, si se define un atributo Color
en cFigura, ste atributo va a estar implcitamente definido (sin necesidad de declararlo) en cElipse,
cCuadrilatero y dems. Del mismo modo, un mtodo Mover definido en cFigura tambin lo estar en todos sus
descendientes. La nica excepcin es cuando se redefine un mtodo en una clase descendiente, que oculta al del
mismo nombre de la clase ancestro (este tema va a ser analizado en mayor profundidad en el prximo captulo).
Como dijimos ms arriba, la herencia es una herramienta imprescindible para la reutilizacin del
cdigo. Martin y Odell [10] afirma n que con orientacin a objetos se reutiliza en promedio el 80% del cdigo.
Hagamos la analoga en programacin modular tradicional: supongamos que tenemos declarados en
una unidad de biblioteca o paquete el TDA cCuadrilatero y queremos trabajar con un tipo cTrapezoide.
Sin POO, lo nico que podremos hacer es declarar el tipo necesario y luego rescribir los
subprogramas que manejen ese tipo, copindolos de los de cCuadrilatero y adaptndolos. Parece un trabajo
bastante pesado.
Pero eso no es todo. Y si no se cuenta con el cdigo fuente del TDA, por ejemplo, porque est en
una biblioteca compilada comprada? En este caso se debern escribir los subprogramas, pero desde cero, sin
ningn tipo de ayuda. Parece ser bastante difcil lograr que dichos subprogramas se comporten de manera
similar a los de la biblioteca: uno no puede saber qu consideraciones pasaron por la mente del implementador.
Un paliativo puede ser utilizar composicin, pero eso no me librara de la necesidad de reescribir
gran parte del cdigo, adems de utilizar un concepto incorrecto: un trapezoide no contiene un cuadriltero, es

- 39 -

CARLOS FONTELA

un cuadriltero.
Pero si esta biblioteca est desarrollada utilizando objetos, lo nico que se debe hacer es extenderla
con las clases necesarias, teniendo que desarrollar muy poco cdigo. Como se ve, trabajar con POO puede
proporcionarnos un considerable ahorro de tiempo y dinero.
Para que todo esto sea estrictamente cierto, se debe construir el rbol de clases de una forma estricta,
cuidando de colocar cada clase donde deba ir. Una ayuda en este sentido es utilizar la recomendacin de que la
relacin subclase - superclase sea del tipo "es un".
Cmo hace un arquelogo que encuentra un nuevo tipo de escritura desconocido, en unas tablillas
de barro cocido, y debe determinar a qu pueblo pertenece y de qu familia es? Precisamente, debe tratar de
agregarla en el rbol de idiomas actual. Determinar si la lengua es de origen indoeuropeo, semtico u otra. Una
vez que determina que es de la familia indoeuropea tal vez deba determinar si es cltica, germnica, eslava,
escandinava, irania, ndica, mediterrnea antigua, caucsica, etc. En fin: lo mismo debemos hacer nosotros al
construir nuestro rbol de clases25 .
Herencia mltiple
Supongamos que en la jerarqua de figuras geomtricas discriminramos tipos de tringulos, y
declaramos tres clases derivadas: rectngulos, acutngulos y obtusngulos.
Sin embargo, otro programador podra necesitar una jerarqua diferente, como dividir a los tringulos
en equilteros, issceles y escalenos.
Si superponemos ambas jerarquas, llegaramos a:

CTriangulo

cTRectangulo

cAcutangulo

cObtusangulo

cIsosceles

cEquilatero

cEscaleno

cRectanguloIsosceles

El problema conceptual aqu es que, considerando ambas visiones, las clasificaciones dejaron de ser
excluyentes. Como consecuencia, si deseamos crear una clase de los tringulos que son a la vez rectngulos e
issceles, deberamos declararla con dos ancestros. Este concepto se denomina herencia mltiple .
La herencia mltiple es una herramienta poderosa de diseo y algunos lenguajes, como C++ y
Smalltalk, la soportan, mientras otros, como Java y Object Pascal, no.
Sin embargo, es una caracterstica que debe usarse con cuidado, sobre todo por las ambigedades que
se generan si una clase tiene dos padres cuyas estructuras o comportamientos se solapan, lo que ocurre ms a
menudo de lo que se cree.
Por estos inconvenientes, y por no estar disponible en todos los lenguajes orientados a objetos, no
estudiaremos la herencia mltiple.
Cuando necesitamos heredar, por un lado estructura y comportamiento, y por otro ciertos mtodos, se
puede mantener la herencia para el primer caso y hacer uso de interfaces para el segundo. Java y Object Pascal
25

Tratando de saber ms del problema de lo que s yo de familias idiomticas.

- 40 -

PROGRAMACIN ORIENTADA A OBJETOS

soportan interfaces, C++ no.


Dejaremos el estudio de interfaces para ms adelante en este captulo.
Herencia con excepciones
A veces se necesitan definir excepciones a la herencia, en todas las disciplinas. Por ejemplo, tal vez
queramos definir a las aves como animales voladores, con excepciones como los pinginos, las gallinas, etc..
Otro ejemplo puede ser definir a los idiomas que se hablan en Europa como indoeuropeos, con las excepciones
del magiar, el fins y el turco. Y as sucesivamente.
De todas maneras, el uso de herencia con excepciones es una prctica cuestionable, ya que tal vez se
deberan utilizar subclases para expresar las excepciones. En los ejemplos anteriores, se podran clasificar los
pases europeos en aquellos de lenguas indoeuropeas y aquellos de lenguas no indoeuropeas, o las aves en
voladoras y no voladoras. De esta manera se corrige la inconsistencia lgica.
Sin embargo, estas clasificaciones con subclases no permiten excepciones por diferentes categoras y
elimina jerarquas que pueden ser interesantes. Por ejemplo, si deseo clasificar a las aves en voladoras y no
voladoras, no voy a poder clasificarlas tambin como americanas y europeas sin caer en la herencia mltiple.
De all que la herencia con excepciones tenga sus defensores, por lo menos en el terreno terico.
Especializacin con menos atributos
Ya dijimos que la herencia se debera dar entre clases cuando se les pueda aplicar la relacin "es un".
Si no fuera as, la herencia de atributos y comportamiento se puede hacer caprichosa y sin sentido.
Sin embargo, a veces estamos tentados de plantear excepciones a esta regla.
Por ejemplo, un implementador de una aplicacin que dibuje figuras geomtricas se puede sentir
tentado de declarar a la clase cElipse como descendiente de la clase cCircunferencia , agregndole, como
atributo, un radio ms; sin embargo, esto viola el principio bsico de la herencia, ya que una circunferencia,
aunque tenga un atributo menos, es una elipse y no lo contrario. Pero, cmo hacemos para declarar una
subclase que tiene menos atributos que su ancestro? Algo parecido pasara con clases para definir matrices y
matrices cuadradas (ver el ejercicio que se presenta ms adelante en este captulo).
Los ejemplos que acabamos de ver son muy comunes en POO. Pero este problema no se ha resuelto
en ningn lenguaje de programacin orientado a objetos, y tal vez su solucin sea una de las futuras mejoras en
las tcnicas de desarrollo de software.
La nica manera de representar una clase con menos atributos que su ancestro es hacer que ningn
mtodo acceda al atributo en cuestin, y simultneamente hacerlo privado.
Tambin podra pensarse en evitar la herencia de mtodos. En este campo, la solucin puede estar en
la redefinicin (que veremos luego).
Constructores, destructores, herencia y composicin
Para asegurar que toda la asignacin de memoria e inicializacin se hace en la forma correcta,
conviene, dentro de un constructor, llamar al principio al constructor de la clase ancestro inmediato, y dentro de
un destructor, llamar al final al destructor de la clase ancestro inmediato.
En Object Pascal:
constructor cClase.Create;
begin
inherited Create;
{ ... }
end;

- 41 -

CARLOS FONTELA

destructor cClase.Destroy;
begin
{ ... }
inherited Destroy
end;

En Java y en C++, en cambio, estas reglas se cumplen en forma automtica, por lo que el segmento
de cdigo no debe incluir la invocacin al constructor del ancestro, salvo cuando hay ms de un constructor en
la clase ancestro o ste tiene parmetros. Recordemos que en Java no hay destructores, pero s en C++, y los
destructores de las clases ancestros son llamados con las mismas reglas que hemos recomendado26 .
En cuanto a la composicin, conviene aprovechar el constructor de la clase contenedora para llamar
al constructor de la clase contenida. Ntese que en ningn lenguaje se garantiza que los constructores de los
atributos que son objetos contenidos sean invocados correctamente, por lo que esto queda a cargo del
programador.
Atributos y mtodos protegidos
Adems de los calificadores ya vistos, public y private, que se aplican a los atributos y mtodos para
especificar su grado de visibilidad, existe el calificador protected en los tres lenguajes en los que estamos
trabajando.
El significado de protected en C++ y Object Pascal es que la visibilidad de estos atributos y mtodos
va a ser privada, pero con el agregado de que van a ser visibles para las clases descendientes. En Java implica
que la visibilidad ser la de un atributo o mtodo de acceso friendly adems de ser visible para las clases
descendientes.
Generalizacin, especializacin e instanciacin
A estos tres conceptos los queremos distinguir claramente.
En primer lugar, la generalizaci n es la operacin a hacer para obtener el ancestro de una clase.
La especializacin, en cambio, es la operacin a hacer para obtener las subclases de una clase ms
general. Es la inversa de la anterior.
La instanciacin es la operacin a hacer para obtener un objeto de una clase. No tiene relacin
alguna con las anteriores, pues no es una relacin entre clases, sino entre una clase y un objeto o instancia. Se
obtiene un objeto individual, aunque tambin debe cumplir la relacin es un, como en la herencia .

INTERFACES
Concepto de interfaz
Las interfaces, que en algunos lenguajes se llaman protocolos, son un interesante mecanismo para
declarar algunas operaciones que deben implementar ciertas clases.
Supongamos, por ejemplo, que queremos declarar una operacin Guardar, que permita a un objeto
guardarse a s mismo en un archivo, y que pueda servir para muchas clases, aunque tenga distintas
implementaciones en cada una.
Una primera solucin sera poner el mtodo en la clase base de la familia en la cual quiero
26

Salvo cuando haya ms de un destructor o cuando se precise pasarle parmetros.

- 42 -

PROGRAMACIN ORIENTADA A OBJETOS

implementar la operacin. Pero puede ocurrir que esa operacin no deba ser implementada en todas las clases
de la familia, y s se necesite implementarla en clases de otras familias. Es decir, puede haber clases cuyos
objetos sean guardables que pertenezcan a distintas familias, a la vez que no todas las clases de una familia
puedan ser guardables. En estos casos, no nos sirve el uso de herencia.
Otra posibilidad sera la herencia mltiple, en los lenguajes que la soportan. De esta manera,
podramos hacer que la clase en cuestin tuviera un ancestro que representa su familia y otro que contiene los
mtodos a implementar. Pero ocurre que estaramos violando la condicin de que la herencia exprese siempre
relaciones del tipo es un.
Las interfaces proponen una solucin ms elegante y consistente.
Una interfaz es una coleccin de operaciones que especifican un servicio. Sirve para encapsular un
conjunto de mtodos, sin asignar esta funcionalidad a ningn objeto en particular ni expresar nada respecto del
cdigo que las va a implementar. Dicho de otra manera, una interfaz describe cmo se va a utilizar un
determinado mtodo, pero no restringe qu objetos o clases lo van a poder utilizar ni cmo.
Una interfaz especifica un contrato, que permite que cambien cliente o proveedor en la medida que
cada uno cumpla lo especificado en el contrato.
Su declaracin tiene una estructura parecida a la de una clase, pero sus mtodos no se implementan,
sino que deben ser redefinidos en las clases que implementen la interfaz. Los mtodos de una interfaz deberan
ser pblicos para permitir la redefinicin 27 .
En algunos lenguajes, las interfaces pueden tener atributos, pero stos sern atributos de clase y con
valor constante.
Decimos que una clase implementa una interfaz, cuando la clase se compromete a implementar todos
los mtodos de la interfaz.
Como una clase puede implementar varias interfaces a la vez, podra haber conflictos de nombres
que se resolvern con las reglas de resolucin de mbito de cada lenguaje. No obstante, es recomendable no
repetir nombres de mtodos en distintas interfaces que sirvan a una misma familia de clases.
Las interfaces pueden tener interfaces descendientes, y una clase puede implementar interfaces a la
vez que hereda de otra clase.
Ntese que, debido a que las clases que implementan una determinada interfaz no tienen por qu ser
descendientes de un ancestro comn, esto permite algo parecido a la herencia mltiple, ya que por la herencia
se heredan los mtodos de su clase ancestro, mientras que mediante interfaces se heredan mtodos que no
provienen de una jerarqua. De todas maneras, recordemos que los mtodos provenientes de una interfaz no
tienen implementacin y deben implementarse en las clases que la utilicen.
Las interfaces estn presentes slo en algunos lenguajes de POO, como Java y Object Pascal. En
otros, como C++, deben simularse con herencia mltiple.
Por otro lado, el OMG (Object Management Group) recomienda la implementacin de interfaces
para garantizar la interoperabilidad de objetos distribuidos. Por ello es que la tecnologa CORBA hace un uso
intenso de interfaces.
Un ejemplo de interfaces: la clase adaptadora
A menudo es necesario tratar con el mismo nombre a mtodos de clases diferentes, que incluso
pueden tener encabezados diferentes.
Supongamos, por ejemplo, que tenemos una clase cLibro, provista por un servicio remoto
denominado LibreriaVirtual, que devuelve el precio de un libro llamando al mtodo precio. Simultneamente,
el servicio remoto LaGranTienda ha implementado una clase cArticulo, que incluye libros, y que tiene un
27

En Java tambin podran ser friendly.

- 43 -

CARLOS FONTELA

mtodo esLibro, que indica si es o no un libro, y otro precioArticulo , que devuelve el precio de un artculo.
Qu ocurrira si deseo acceder a precios de libros con una sintaxis uniforme, digamos mediante un mtodo
precioLibro?
Una solucin sera construir una interfaz que luego se implementara en una clase adaptadora, como
muestra este fragmento en Java:
public interface ConsultaPrecios {
public double precioLibro();
}

Ntese que, hasta el momento, no hemos dicho nada de cmo se implementa precioLibro, sino que
slo hemos definido su encabezado, y hemos declarado que toda clase que implemente la interfaz
ConsultaPrecios deber implementar precioLibro.
Entonces ahora vamos a definir las clases adaptadoras:
// clase adaptadora para el servicio LibreriaVirtual
// archivo AdaptadoraLibreriaVirtual.java
import ar.com.LibreriaVirtual.cLibro;
public class AdaptadoraLibreriaVirtual implements ConsultaPrecios {
private cLibro libro;
public AdaptadoraLibreriaVirtual(cLibro l) {
libro=l;
}
public double precioLibro() {
return libro.precio();
}
}
// clase adaptadora para el servicio LaGranTienda
// archivo AdaptadoraGranTienda.java
import cl.com.LaGranTienda.cArticulo;
public class AdaptadoraGranTienda implements ConsultaPrecios {
private cArticulo libro;
public AdaptadoraGranTienda (cArticulo a) {
libro=a;
}
public double precioLibro() {
if (libro.esLibro())
return libro.precio();
else
throw new UnsupportedOperationException();
}
}

Las clases adaptadoras son un clsico patrn de diseo, como vamos a ver al estudiar patrones de
diseo. Pueden usarse en vez de las subclases. Incluso tienen algunas ventajas, como el hecho de que en una
clase adaptadora se puede restringir la visibilidad, cosa que nunca puede hacerse en una clase descendiente. Sin
embargo, las clases descendientes tienen ya prevista la transformacin de tipos automtica hacia arriba en
muchos casos, cosa que no es as en las clases adaptadoras.

- 44 -

PROGRAMACIN ORIENTADA A OBJETOS

ELECCIN DE IMPLEMENTACIN: COMPOSICIN, HERENCIA O INTERFACES?


Muchas de las personas que se enfrentan por primera vez con la POO terminan creyendo que la
herencia debe usarse siempre que sea posible. Pero la verdad es que siempre hay que analizar si en un
determinado caso no conviene la composicin, que es sencilla de implementar y ms flexible.
Por ejemplo, parecera obvio que una pila que se implementa con arreglos debera contener un vector
como uno de sus atributos. Sin embargo, la implementacin de pilas de Java 1.0/1.1 est construida como una
subclase de Vector. Esto es tan contraproducente que permite que se usen todos los mtodos de Vector para
trabajar con pilas.
En general, se usa composicin cuando se necesitan algunos aspectos de la clase contenida, pero no
su comportamiento. De esta manera, se podr usar la funcionalidad de la clase contenida, pero a travs de la
interfaz de la clase contenedora. En cambio, si se quiere tener la misma interfaz de la clase contenida, se
debera usar herencia. Dicho de otro modo, la herencia se usa cuando una interfaz parece apropiada para
incorporar ms comportamiento o distinta funcionalidad (una nueva versin).
La herencia fue pensada ms bien para permitir el desarrollo incremental, para lo cual es una
herramienta mucho ms poderosa que la composicin.
Histricamente, la construccin de jerarquas de clases se ha hecho siguiendo bsicamente dos
principios.
El primero de ellos es el de la relacin es un, tambin llamado principio de sustitucin28 . Es el
que hemos usado siempre en este curso, por ser el ms estable y recomendable, garantizar mejor la reutilizacin
y extensin y el que utilizan las ciencias para sus taxonomas. En base a este principio se ubica un objeto en su
clase, o una clase en una jerarqua, mediante pruebas de reconocimiento. Tambin se la llama herencia
conceptual.
El otro es el de la relacin es parte de. ste es menos recomendable. Si bien no es tcnicamente
una herencia, parecindose ms a la composicin, a veces se la llama herencia de implementacin. Sera
bueno dejar este caso para resolverlo con composicin y no con herencia.
Hemos dicho que las interfaces solucionan la mayor parte de los problemas que se implementan con
herencia mltiple, y de una forma ms elegante y simple. Sin embargo, tampoco es cuestin de forzar las
interfaces para lograr herencia mltiple, como muchos autores han pretendido.
Tambin la composicin es un buen instrumento para evitar la herencia mltiple en muchos casos.

IMPLEMENTACIN DE REUTILIZACIN DEL CDIGO EN DISTINTOS LENGUAJES


Composicin, herencia e interfaces en Object Pascal
En Object Pascal, todas las clases declaradas con la palabra class que no se declaran con un ancestro
inmediato tienen una clase ancestro por omisin llamada TObject. En ese ancestro por omisin estn definidos
un constructor Create y un destructor Destroy, que deben redefinirse en cada descendiente siguiendo las
recomendaciones que se mencionaron ms arriba29 .
Adems, el modelo de memoria de TObject es tal que los objetos instancias de esta clase y sus
descendientes se alojan en memoria dinmica. La declaracin de un objeto slo reserva lugar para una
referencia (una especie de puntero), pero no para el objeto en s. Por eso, es en tiempo de ejecucin que hay que
invocar al constructor que, adems de lo que indique su cdigo, asignar un lugar de memoria para el objeto
28

Algunos entienden este principio como la restriccin de no agregar ningn atributo ni mtodo, pero s redefinicin.
En realidad, los constructores y destructores pueden tener el nombre que ms le guste al programador, pero hay muchas aplicaciones
que cuando utilizan clases y componentes Delphi buscan explcitamente un constructor Create y un destructor Destroy.
29

- 45 -

CARLOS FONTELA

respectivo. De todas maneras, todo esto es transparente al usuario, pues la notacin que se utiliza no es la de
punteros en Pascal sino la tradicional de objetos. Como es relativamente obvio, la liberacin de memoria se
hace invocando al destructor.
Este uso de referencias tiene la ventaja de la flexibilidad a costa de un mayor tiempo de ejecucin en
el momento de crear y destruir objetos 30. Otro inconveniente es el problema de los alias en asignaciones y
pasaje de parmetros, que se da usualmente al trabajar con punteros 31 , que se puede subsanar escribiendo un
mtodo que asigne un objeto a otro.
Adems, este modelo de memoria es el recomendado por el OMG (Object Management Group) para
garantizar la interoperabilidad de objetos distribuidos.
Como la notacin de punteros de Pascal no es necesaria cuando se trabaja con objetos, en Object
Pascal se pueden implementar estructuras de datos dinmicas sin usar punteros explcitos.
Cualquier objeto puede contener otros objetos, de modo tal que la composicin se hace de forma
natural. Lo nico que hay que recordar es que, en realidad, lo nico que se guarda en el objeto contenedor es
una referencia al objeto contenido.
La herencia se indica poniendo entre parntesis el nombre de la clase ancestro inmediato, como a
continuacin:
type cElipse = class (cFigura)
{ declaraciones de atributos y mtodos }
end;

Desde un mtodo redefinido se puede llamar al mtodo que se est redefiniendo en la clase ancestro,
usando la palabra inherited , como ya se mostr al hablar de constructores y destructores.
Las interfaces se parecen a las clases, pero sus mtodos no tienen implementacin. A continuacin se
muestra la declaracin de una interfaz:
type iPersistente = interface
procedure Guardar;
function Recuperar : TObject;
end;

Para implementar una interfaz en una clase hay que hacerlo poniendo a la interfaz como si fuera una
clase ancestro y ponindola a continuacin de su ancestro inmediato, como en:
type cTriangulo = class (cFigura, iPersistente)
{ declaraciones de atributos y mtodos }
end;

Se pueden declarar variables que sean instancias de interfaces, aunque cuando se las cree se deber
hacerlo llamando a un constructor que implemente esa interfaz pero que sea de una clase con implementacin.
Esto va a implicar el uso abundante de moldeo hacia abajo, que se analiza luego.
As como hay una clase TObject, ancestro de todas las clases por defecto, existe tambin IInterface,
ancestro de todas las interfaces32 .
Composicin y herencia simple y mltiple en C++
El modelo de memoria de C++ para objetos es el mismo que en el resto de los tipos. Es decir,
30

Aunque en Delphi est bastante optimizado.


Por ejemplo, si escribimos A := B, siendo A y B referencias o punteros, A queda apuntando a la misma direccin de B, por lo que en
realidad son la misma variable. Lo mismo ocurre con parmetro y argumento si llamamos a un subprograma P(B) y B es un puntero o
referencia.
32
Esto es as desde Delphi 6. Hasta Delphi 5 se usaba IUnknown como ancestro de ltima instancia de las interfaces.
31

- 46 -

PROGRAMACIN ORIENTADA A OBJETOS

mientras no se diga otra cosa, todos los datos se alojan en memoria esttica. Si se quiere utilizar memoria
dinmica se deben utilizar punteros.
La ventaja inocultable de este modelo es la velocidad de ejecucin, aunque se puede desperdiciar
espacio de memoria por la necesidad de asignarla antes de conocer cunta se necesitar exactamente.
Como contra adicional, este modelo de memoria no cumple con las recomendaciones del OMG
(Object Management Group) para garantizar la interoperabilidad de objetos distribuidos.
Cualquier objeto puede contener otros objetos, de modo tal que la composicin se hace de forma
natural. Hay que recordar que, en estos casos, salvo que se utilicen punteros, se guarda el objeto contenido
dentro del objeto contenedor.
La herencia se indica poniendo a continuacin dos puntos y el nombre de la clase ancestro inmediato,
como a continuacin:
class cElipse : public cFigura
{
// declaraciones de atributos y mtodos
}

Ntese que delante de la clase ancestro se puede poner un atributo de visibilidad: pblico, privado o
protegido. Si se hace una herencia privada significa que los atributos y mtodos de la clase ancestro sern
privados en la clase que se define, de modo que no podrn usarse en sus derivadas. Si, en cambio, se declara a
la herencia como protegida, los atributos y mtodos pblicos y protegidos de la clase ancestro sern protegidos
en la clase que se est declarando. Si, finalmente, se declara una herencia pblica, todos los atributos y mtodos
de la clase ancestro mantienen sus reglas de visibilidad en la clase actual.
Desde un mtodo redefinido se puede llamar al mtodo que se est redefiniendo en alguna clase
ancestro, usando el operador :: de resolucin de mbito.
Como ya dijimos, C++ define un constructor y un destructor por omisin para cada clase. Adems,
stos invocan automticamente al constructor o destructor, respectivamente, de su clase ancestro inmediata.
Para definir otros, se hace con el nombre de clase para los constructores y con el nombre de clase precedido de
~ para los destructores.
Si una clase hereda de ms de un ancestro inmediato (herencia mltip le), la invocacin de sus
constructores se hace segn el orden en que fue declarada la herencia (de izquierda a derecha) y la de sus
destructores en forma inversa a ste (de derecha a izquierda).
La herencia mltiple se hace poniendo ms de una clase en la lista de los ancestros, como:
class cTRectIsos : public cTRectangulo, public cTIsosceles
{
// declaraciones de atributos y mtodos
}

C++ permite definir clases base virtuales para resolver ambigedades en herencia mltiple. Lo que
logran estas clases base virtuales es que exista slo una copia de los atributos y mtodos de sus ancestros en sus
clases derivadas. Si no se declaran virtuales, habr una copia de los mtodos y atributos por cada clase base que
los tenga, aun teniendo el mismo nombre, debiendo resolverse de alguna forma la ambigedad.
Como ya dijimos, las interfaces no estn soportadas en C++, pero pueden simularse con mtodos
abstractos (los veremos en el prximo captulo) y herencia mltiple.
Composicin, herencia e interfaces en Java
En Java, todas las clases que no se declaran con un ancestro inmediato tienen una clase ancestro por
omisin llamada Object.
El modelo de memoria de Object es tal que los objetos instancias de esta clase y sus descendientes se

- 47 -

CARLOS FONTELA

alojan en memoria dinmica. La declaracin de un objeto slo reserva lugar para una referencia (una especie de
puntero), pero no para el objeto en s. Por eso, es en tiempo de ejecucin que se invoca al constructor que,
adems de lo que indique su cdigo, asignar un lugar de memoria para el objeto respectivo. De todas maneras,
todo esto es transparente al usuario, pues la notacin que se utiliza es la tradicional de objetos. La liberacin de
memoria no se hace mediante destructores, que en Java no existen, sino que la hace el recolector automtico de
basura.
Este uso de referencias tiene la ventaja de la flexibilidad a costa de un mayor tiempo de ejecucin en
el momento de crear objetos 33. Otro inconveniente es el problema de los alias en asignaciones y pasaje de
parmetros, que se da usualmente al trabajar con punteros 34 , que se puede subsanar escribiendo un mtodo que
asigne un objeto a otro.
Adems, este modelo de memoria es el recomendado por el OMG (Object Management Group) para
garantizar la interoperabilidad de objetos distribuidos.
Un problema del recolector de basura, es que nunca se puede asegurar cundo va a ser invocado 35 ,
por lo que no se pueden determinar tiempos iguales para procesos iguales ni establecer cundo se realizan las
tareas que se ejecutan al ponerse en funcionamiento el recolector de basura. En Java existe un mtodo finalize()
que se puede declarar para cada clase, para ser invocado cuando se active el recolector de basura. Pero no hay
forma de saber en qu momento ocurrir esto, y en un programa chico o corriendo en una mquina de mucha
memoria tal vez no ocurra nunca. Por lo tanto, finalize() no es tampoco un destructor, y no se usa demasiado.
Dentro de finalize() se debera invocar al finalize() de la clase ancestro de la misma forma que se describe para
destructores en C++ y Object Pascal. Por lo tanto, si se desean ejecutar algunas acciones antes de dejar de usar
un objeto, el programador se debe preocupar de insertarlas en el cdigo apropiadamente.
Se puede alegar que la recoleccin de basura es lenta, pero al decir esto estaramos olvidando que no
siempre se la hace, sino slo cuando es necesaria, con lo cual puede incluso llegar a mejorar el desempeo de la
aplicacin.
Cualquier objeto puede contener otros objetos, de modo tal que la composicin se hace de forma
natural. Lo nico que hay que recordar es que, en realidad, lo nico que se guarda en el objeto contenedor es
una referencia al objeto contenido.
La herencia se indica poniendo a continuacin la palabra extends y el nombre de la clase ancestro
inmediato, como a continuacin:
class cElipse extends cFigura {
// declaraciones de atributos y mtodos
}

Desde un mtodo redefinido se puede llamar al mtodo que se est redefiniendo en la clase ancestro,
usando la referencia a super:
public void M (int X, int Y) {
super.M(X);
// llama al M de la clase ancestro
System.out.println(Y);
}

En el caso de los constructores, la llamada a super se hace sin indicacin de mtodo:


super();

Como ya dijimos, Java define un constructor por omisin para cada clase. Adems, ste invoca
33

Aunque en casi todas las implementaciones de Java est muy optimizado.


Por ejemplo, si escribimos A = B, siendo A y B referencias o punteros, A queda apuntando a la misma direccin de B, por lo que en
realidad son la misma variable. Lo mismo ocurre con parmetro y argumento si llamamos a una funcin P(B) y B es un puntero o
referencia.
35
Salvo que se usen trucos muy sucios en el cdigo.
34

- 48 -

PROGRAMACIN ORIENTADA A OBJETOS

automticamente al constructor de su clase ancestro inmediata. Para definir otros, se hace con el nombre de
clase.
Se puede declarar que un determinado mtodo no va a poder ser redefinido anteponindole la palabra
final.
Se puede declarar una clase como final para que no se puedan construir clases derivadas de la misma.
De todas maneras, es preferible evitar declarar mtodos y clases como final porque impiden reutilizacin y
extensin.
Las interfaces se parecen a las clases, pero sus mtodos no tienen implementacin. A continuacin se
muestra la declaracin de una interfaz:
public interface iPersistente {
public void Guardar();
public Object Recuperar();
}

Para implementar una interfaz en una clase hay que especificarlo a continuacin de la clase ancestro
inmediato, colocando la palabra implements:
class cTriangulo extends cFigura implements iPersistente {
// declaraciones de atributos y mtodos
}

Se pueden declarar variables que sean instancias de interfaces, aunque cuando se las cree se deber
hacerlo llamando a un constructor que implemente esa interfaz pero que sea de una clase con implementacin.
Esto va a implicar el uso abundante de moldeo hacia abajo, que se analiza luego.

EJERCICIO RESUELTO: IMPLEMENTACIN DE MATRICES


Enunciado
Escribir clases que implementen matrices y matrices cuadradas, incluyendo todas las operaciones
posibles. Las operaciones que generen matrices nuevas (suma, producto, etc.) no deben construir la matriz
resultado, que se supone creada en el mdulo invocante.
Solucin en Object Pascal
Ver apndice A: Implementacin de matrices
Solucin en C++
Ver apndice B: Implementacin de matrices
Solucin en Java
Ver apndice C: Implementacin de matrices

- 49 -

CARLOS FONTELA

EJERCICIO RESUELTO: USO DE LA IMPLEMENTACIN DE MATRICES


Enunciado
Escribir un subprograma que, utilizando la implementacin de matrices del ejercicio anterior,
resuelva un sistema de ecuaciones lineales del tipo: A.X=B, haciendo uso de la solucin X=A -1.B.
Solucin en Object Pascal
Ver apndice A: Uso de la implementacin de matrices
Solucin en C++
Ver apndice B: Uso de la implementacin de matrices
Solucin en Java
Ver apndice C: Uso de la implementacin de matrices

- 50 -

PROGRAMACIN ORIENTADA A OBJETOS

5. PROGRAMACIN ORIENTADA A OBJETOS:


POLIMORFISMO
POLIMORFISMO
Polimorfismo y vinculacin tarda
Polimorfismo quiere decir "muchas formas". En POO llamamos polimorfismo a la propiedad que
tienen los mtodos de mantener una respuesta unificada, con la misma semntica, aunque con distinta
implementacin, a travs de la jerarqua de clases. O dicho de otra manera, la llamada a una misma operacin
puede invocar a mtodos distintos. A veces se lo denomina abstraccin de mensajes.
En definitiva, lo que logra el polimorfismo es retardar la decisin sobre el tipo (o clase) del objeto
hasta el momento en que vaya a ser utilizado el mtodo. En este sentido, el polimorfismo est asociado a lo que
se denomina vinculacin tarda o vinculacin en tiempo de ejecucin.
La idea es que los objetos de distintas clases derivadas de otra puedan ser tratados de la misma
manera, y se le apliquen los mismos mtodos, aunque las imp lementaciones particulares sean diferentes.
Esto va a permitir una mayor separacin de interfaz e implementacin y va a dar una nueva ayuda en
pos de la extensin del cdigo. Por qu? Porque una vez que se escriba un mtodo para una clase, la creacin
de clases derivadas no va a implicar redefinirlo cuando tenga una semntica similar.
Como vemos, el polimorfismo es un concepto complejo, y muy ligado a la herencia y el
encapsulamiento. Por eso, vamos a empezar estudiando algunas propiedades que se asocian al polimorfismo
para luego llegar a un anlisis del mismo.
Redefinicin36
La redefinicin es una funcionalidad de la POO que se usa cuando el comportamiento de la clase
ancestro no es exactamente igual para la descendiente.
Por ejemplo, en el caso de las fig uras geomtricas que introdujimos en el captulo anterior, el mtodo
Dibujar puede no ser igual para todas las clases, aunque todas dibujen una figura. En ese caso, tendramos un
Dibujar para cFigura, otro para cElipse, otra para cCirculo, etc.. Simplemente, esto se resuelve escribiendo
diferentes mtodos Dibujar, y decimos que el mtodo Dibujar de una clase descendiente redefine al mtodo
Dibujar de su ancestro. Esta redefinicin se debe a que ahora, cada vez que se invoque al mtodo Dibujar para
una instancia de cCirculo nos estaremos refiriendo, no ya al que se hubiera heredado de cFigura o de cElipse,
sino al redefinido en cCirculo .
Por lo tanto, la llamada a una misma operacin depender de la clase a la que pertenece el objeto.
Por ejemplo 37 :
UnaElipse.Dibujar();
UnCirculo.Dibujar();
UnCuadrado.Dibujar();

Todos se refieren a la operacin Dibujar, pero en realidad estn invocando a implementaciones


diferentes, segn la clase del objeto para el cual se llama al mtodo.
36

Hasta que empec la escritura de esta obra, lo que hoy llamo redefinicin lo haba llamado sobrecarga. Ocurre que la mayor parte
de la literatura utiliza sobrecarga para referirse a la propiedad, en ciertos lenguajes, de que distintos subprogramas pueden tener el
mismo nombre, incluso fuera de la POO. En ingls se los llama overriding y overloading, aunque incluso hay diferencias sobre lo
que overriding quiere decir.
37
La notacin es de Java o C++, pero ocurre lo mismo en Object Pascal.

- 51 -

CARLOS FONTELA

Como principios generales, se debe utilizar redefinicin cuando en una subclase pueda realizarse una
implementacin ms eficiente o ms completa que la de la clase ancestro. En consecuencia, la redefinicin:
?? Ser obligatoria, cuando el comportamiento de una clase descendiente sea diferente del de la
ancestro. Por ejemplo, si hay un mtodo que se llama ImprimirAtributos que imprime todos
los atributos de un objeto, ste deber redefinirse en las clases derivadas si queremos que
funcione correctamente.
?? Ser optativa, cuando por razones de eficiencia o claridad queramos modificar la
implementacin del mtodo del ancestro. Por ejemplo, el mtodo para calcular la longitud de
una elipse probablemente funcione bien con crculos, pero su implementacin es mucho ms
complicada.
?? Debe preservar la semntica de la definicin del mtodo en el ancestro. Es decir que la tarea
debe ser la misma, aunque se haga de diferente forma.
Tengamos en cuanta que la redefinicin se introdujo para cambiar comportamiento de una clase
descendiente respecto del ancestro, no para introducir cambios en la estructura. Por lo tanto, se pueden redefinir
mtodos, pero no atributos.
Los mtodos privados no pueden ser redefinidos. Si se lo intenta, en realidad se estar definiendo un
nuevo mtodo. Al fin y al cabo, la redefinicin slo tiene sentido si el mtodo es parte de la interfaz del
ancestro, y los mtodos privados no son parte de la interfaz.
Sobrecarga y redefinicin
La sobrecarga es un concepto que poco tiene que ver con POO. Exista previamente en lenguajes
como Pascal en la biblioteca estndar, como con los subprogramas Read, Write y dems. En Ada, desde sus
primeras versiones, se poda incluso definir por el programador. Adems, no tiene nada que ver con la
vinculacin dinmica o el polimorfismo.
Sin embargo, hay algunas interacciones con el concepto de redefinicin que nos interesa analizar.
La relacin ms conflictiva de la sobrecarga y la redefinicin se da cuando redefinimos un mtodo en
una clase descendiente con un encabezado distinto al del mtodo ancestro. En este caso, se efectuar una
redefinicin, en el sentido de ocultar la definicin hecha en la clase base? o ms bien se la tratar de un nuevo
mtodo que sobrecargar a los de la clase ancestro? La respuesta a esta pregunta depende de cada lenguaje.
En Object Pascal, como dijimos, se debe poner la palabra overload en todos los mtodos que se
sobrecargan a un mismo nivel. Del mismo modo, si se quiere sobrecargar un mtodo de una clase ancestro se
debe indicar claramente con la palabra overload en la descendiente. Si no se hiciera as, se toma el nuevo
mtodo como una redefinicin, y esto impide el acceso al mtodo de la clase ancestro desde la descendiente.
En Java y en C++, cuando se utilizan encabezados diferentes en una clase ancestro y una
descendiente, esto no redefine el mtodo de la ancestro sino que provoca una sobrecarga. Como corolario, los
mtodos que no se redefinan con el mismo encabezado de la clase base, siguen estando disponibles para la
clase descendiente.
Objetos polimorfos o conversin de tipo automtica
Cuando un programador de un lenguaje procedimental con tipos escribe un subprograma sabe
siempre exactamente de qu tipo van a ser los argumentos que se le pasen.
Pero en POO se puede pasar un argumento cuya clase sea derivada de la clase del parmetro38. Por
38

Si bien algunos autores tratan a los trminos argumento y parmetro como sinnimos, en mis obras tienen un significado
diferente. Argumento significa lo mismo que parmetro actual y parmetro es lo mismo que parmetro formal. Dicho en otros trminos,

- 52 -

PROGRAMACIN ORIENTADA A OBJETOS

ejemplo, estas lneas de cdigo son vlidas en Object Pascal:


type cClaseDerivada = class(cClaseBase)
...
procedure P (X:cClaseBase);
...
var UnObjetoClaseDerivada : cClaseDerivada;
...
P(UnObjetoClaseDerivada);

Ntese que P admite un argumento cuyo tipo es distinto del del parmetro.
Por lo tanto, cuando utilizamos POO, el programador del mtodo desconoce la clase del objeto que
va a recibir como argumento, y ni siquiera el compilador la conoce. Se dice que dicho programador y el
compilador estn trabajando con un objeto polimorfo , del cual slo se conocen los atributos y comportamiento
que hered de la clase del parmetro. Esto permite el procesamiento de objetos cuya clase es desconocida en
tiempo de compilacin.
Esto no es una desventaja ; es una consecuencia positiva de la herencia que provoca importantes
ahorros de tiempo por reutilizacin del cdigo, ya que no es necesario repetir un mismo mtodo para
parmetros de clases distintas.
Hay quien no considera polimorfismo al uso de objetos polimorfos, pues en este caso el mtodo
invocado es siempre el mismo. Sin embargo, para quien establece que siempre que hay vinculacin tarda entre
parmetros y argumentos hay polimorfismo, ste sera un caso.
Mtodos virtuales
Supongamos que en la jerarqua de clases de figuras que ya hemos mencionado, definimos mtodos
Mover , Borrar y NuevasCoordenadas en la clase cFigura , mientras que definimos el mtodo Dibujar en
cFigura, pero lo redefinimos en las clases descendientes:
cFigura
+Dibujar()
+Borrar()
+NuevasCoordenadas()
+Mover()

cElipse
+Dibujar()

cCuadrilatero
+Dibujar()

cTriangulo
+Dibujar()

cOtros
+Dibujar()

Si el mtodo Mover de cFigura se puede escribir (en Object Pascal):


procedure cFigura.Mover (X,Y:Word);
begin
el argumento es parte del mtodo invocante, y el parmetro del invocado.

- 53 -

CARLOS FONTELA

Borrar;
NuevasCoordenadas(X,Y);
Dibujar;
end;

Cmo se hace para que cada vez se llame al mtodo Dibujar correcto?
Precisamente, si se hace vinculacin tarda, podemos lograr que el Dibujar que se invoque
corresponda siempre al objeto para el cual se invoc Mover. Es decir:
UnaElipse.Mover;
{ llamar al Mover de cFigura pero con el Dibujar de cElipse }
UnCuadrilatero.Mover;
{ llamar al Mover de cFigura con el Dibujar de cCuadrilatero }

Veamos otro ejemplo en Object Pascal (donde cVectorFiguras es un vector de elementos cFigura):
procedure cVectorFiguras.DibujarTodas;
var I : Word;
begin
for I := 1 to CantFiguras do
Vector[I].Dibujar;
end;

De nuevo, la vinculacin tarda garantiza que el Dibujar invocado es el que corresponde a la clase
del elemento del vector (que podr ser de cualquier descendiente de cFigura).
Los mtodos que son vinculados dinmicamente o tardamente se denominan mtodos virtuales. En
los ejemplos anteriores, Dibujar debera ser un mtodo virtual para garantizar la vinculacin tarda.
Hay lenguajes, como Smalltalk y Java, que toman la vinculacin tarda por omisin, por lo cual todos
los mtodos son virtuales. Otros, como C++ y Object Pascal, requieren que el programador especifique el
mtodo como virtual explcitamente.
Las reglas generales para el uso de mtodos virtuales son que un mtodo debe ser virtual en alguna
de estas circunstancias:
?? Cuando est redefinido y es llamado desde un mtodo no redefinido en la clase ancestro.
?? Cuando est redefinido y es invocado desde un mtodo de una clase compuesta con algn
objeto de una clase ancestro.
Los mtodos virtuales suelen consumir ms recursos (memoria y/o tiempo de eje cucin) que los
estticos. Sin embargo, en orden a la reutilizacin, ante la duda, un mtodo debe ser virtual.
Constructores y destructores virtuales
Los destructores casi siempre son virtuales. De ese modo, si se escribe un mtodo en una clase base
que in voca a un destructor virtual, se puede asegurar que siempre llama al destructor de la clase correcta.
Por ejemplo, en Object Pascal, el destructor Destroy es virtual, de all que en todos nuestros ejemplos
en ese lenguaje hayamos puesto la directiva override en los Destroy redefinidos. A su vez, como Destroy no
hace una verificacin de que la referencia est sin apuntar a nada, existe un mtodo que llama al Destroy de
TObject que se denomina Free, que hace esta verificacin. A su vez, tambin en TObject existe el mtodo
FreeAndNil, que hace lo mismo que Free pero poniendo la referencia en nil, de modo que es el ms seguro de
los tres. La idea, entonces, es redefinir Destroy en todas las clases en que sea necesario, pero invocar siempre a

- 54 -

PROGRAMACIN ORIENTADA A OBJETOS

FreeAndNil, que por estar definido en TObject se pude utilizar en todas las clases sin redefinirlo, y estamos
asimismo seguros de que invoca al Destroy de nuestra clase por ser ste virtual.
En C++ es importante que los destructores sean virtuales por las mismas razones.
Los constructores, en cambio, no suelen ser virtuales. Para empezar, un constructor se usa para crear
un objeto, parece un poco raro crear uno sin saber su clase de antemano. De hecho, ni en C++ ni en Object
Pascal se pueden declarar constructores virtuales, salvo haciendo algunos artificios.
De todas maneras, si se desease una funcionalidad polimrfica en un constructor, se puede escribir un
mtodo virtual que llame a un constructor.
En Object Pascal debe hacerse:
type cClaseAInstanciar = class of cClase1;
function CrearObjeto (Tipo: cClaseAInstanciar): cClase1;
begin
Result:= Tipo.Create(....);
end;

Grados de polimorfismo
Ahora que hemos visto varios comportamientos polimrficos en POO, volvamos al anlisis del
propio polimorfismo. Debe entenderse que lo fundamental del polimorfismo es que rompe con la tpica
vinculacin temprana de los lenguajes compilados tradicionales, que vinculan en tiempo de compilacin la
llamada a un subprograma con la direccin absoluta de ste.
El primer paso hacia el polimorfismo lo dimos con la herencia y la redefinicin. De hecho, un
mtodo acta, no slo sobre objetos de la clase para la cual fue declarado, sino para cualquier clase
descendiente de aqulla. Aqu hay polimorfismo al nivel del parmetro invisible Self/this.
Los objetos polimorfos son un segundo grado de polimorfismo, que amplan el campo de la herencia
a la relacin parmetro - argumento. En este caso hay polimorfismo al nivel de todos los parmetros del
mtodo.
Finalmente, con los mtodos virtuales y la vinculacin tarda, se ha dado un paso ms: se ha logrado
que se demore hasta el tiempo de ejecucin la decisin sobre qu mtodos invocar dentro del cdigo de otro
mtodo 39 . Es el objeto quien realiza la accin en una manera apropiada a s mismo (y no a la clase donde est
declarado el mtodo). Hay polimorfismo a nivel de cdigo del mtodo.
Es obvio que el polimorfismo nos presta un especial servicio para la reutilizacin y la extensibilidad.
En programacin tradicional Pascal deberamos escribir un subprograma para cada tipo de dato, repitiendo
tediosamente segmentos de cdigo. Con la vinculacin tarda, un mtodo escrito para una clase podr seguir
funcionando bien aun cuando se agreguen clases derivadas que no estaban siquiera previstas por el
programador del ancestro.

CLASES Y MTODOS ABSTRACTOS


Clases abstractas
A veces es necesario definir clases para las cuales no tiene sentido crear instancias.
Un caso podra ser nuestra ya habitual cFigura, dado que las clases del nivel inmediato inferior
cubren todos los casos posibles. Es decir, una figura en particular ser cElipse, cCuadrilatero o cOtros, pero
nunca directamente una cFigura. En cualquier taxonoma ocurre lo mismo.
39

En tiempo de compilacin lo nico que se hace es una verificacin de tipos y cantidad de argumentos y parmetros y valor devuelto.

- 55 -

CARLOS FONTELA

Estas clases se denominan clases abstractas , y tienen como nica finalidad la declaracin de
atributos y mtodos comunes que luego se utilizarn en las clases descendientes. Dicho formalmente, se
construyen para generalizar estructura y comportamiento comunes de varias clases descendientes. En otros
casos ni siquiera poseen atributos o mtodos, sin o que slo se las define para luego declarar subclases que por
algn motivo se las desea tratar como de la misma familia.
En el ejemplo anterior, aunque cFigura no tenga instancias, nos sirvi para declarar el mtodo
Mover, de modo que las clases descendie ntes lo pudieran usar.
Las interfaces son un caso especial de clase abstracta. Por eso, si una clase abstracta no necesita
implementar mtodos o atributos, habra que analizar si no debiera ser una interfaz.
Mtodos abstractos
Hay otro aspecto parecido al de las clases abstractas. Lo explicaremos con el ejemplo que estamos
analizando.
El mtodo Dibujar de la clase cFigura nunca ser invocado, pues no hay instancias de cFigura y est
redefinido en todas las clases descendientes. Una primera solucin, incorrecta, sera suprimirlo y dejarlo
solamente en las clases hijas. Sin embargo, si hacemos eso, nos encontraremos con que el mtodo Mover de
cFigura no podra ser compilado, ya que en su cdigo fuente invoca a Dibujar, que no est declarado en la
clase cFigura ni en ninguno de sus ancestros. Lo mismo ocurrira con el DibujarTodas de cVectorFiguras que
escribimos ms arriba.
La mejor solucin, entonces, sera escribir el mtodo Dibujar en cFigura, convirtindolo en mtodo
abstracto, esto es, en un mtodo que no puede ser invocado por ninguna instancia de la clase cFigura , aunque
existiera, pero que sirve para que se pueda escribir el mtodo Mover de cFigura tal como se hizo.
Como consecuencia de lo dicho anteriormente, los mtodos abstractos:
?? Siempre deben ser redefinidos, y en algn nivel inferior de la jerarqua deben dejar de ser
abstractos, ya que no se los puede invocar directamente.
?? Deben ser virtuales.
?? No tienen cdigo fuente ejecutable.
?? Son fundamentales en jerarquas de una complejidad mediana.
?? Son necesarios cuando en la clase ancestro hay que utilizarlos en la implementacin de otro
mtodo (como explicamos en el ejemplo con cFigura y cVectorFiguras).
Ntese en el ejemplo del vector de figuras que el DibujarTodas de cVectorFiguras no debera ser
abstracto, ya que l mismo debera ser invocado directamente.
Los mtodos de las interfaces son, por definicin, todos abstractos.
Clases utilitarias y clases sin estado
Las clases utilitarias son clases abstractas que sirven para definir constantes, mtodos que no
dependen de una clase en particular y dems. La idea es que para cada aplicacin, mdulo o familia de
aplicaciones haya una clase en la cual definimos todos los objetos, constantes y clases comunes. Este es un
concepto fundamental en lenguajes como Java, en los cuales todo identificador debe definirse dentro de una
clase.
As haremos en los ejercicios que sigan en Java para definir constantes o mtodos de clase.
Un caso extremo son las clases sin estado, como las que definen familias de funciones en Java. Un
ejemplo es la clase Math , que contiene mtodos de uso matemtico.

- 56 -

PROGRAMACIN ORIENTADA A OBJETOS

USO DE INFORMACIN DE TIPOS EN TIEMPO DE EJECUCIN


Transformacin de tipos
En la mayor parte de los lenguajes de programacin tradicionales existe alguna forma de transformar
un valor de un tipo en otro. Pero si bien era algo que poda hacerse en todos los lenguajes, pocas veces era
realmente necesario utilizarlo. Los programadores C saben de esto, y de cmo se puede hacer difcil de probar y
de mantener un programa en el que se hace a buso de esta capacidad del lenguaje (afortunadamente, C++ es ms
restrictivo que C, no permitiendo convertir arbitrariamente tipos muy diferentes).
Por ejemplo, en C, la lnea:
c = (char) x;

transforma el contenido de la variable x en un char y luego lo asigna a c. Esto podra ser factible, por
ejemplo, si x es un entero y c un char.
Lo mismo puede aplicarse en Pascal, aunque en este lenguaje se hace un muy escaso uso de estas
posibilidades. La lnea que sigue transforma un entero en carcter en Pascal:
c = char(x);

Esta propiedad de la transformacin de tipos se suele denominar moldeo, por el uso del verbo ingls
to cast que se aplica en estos casos en el sentido de tomar un papel en una actuacin. Hay tambin quienes lo
denominan usan el barbarismo casteo.
Sin embargo, el concepto de transformacin de tipos y, en forma ms general, de uso de la
informacin sobre tipos en tiempo de ejecucin tiene un valor importante en el contexto de POO cuando se usa
en conjunto con el polimorfismo y la vinculacin tarda en general.
Moldeo automtico y moldeo explcito
Cuando se trabaja en POO, hay una transformacin de tipos que se hace en forma automtica, que se
da cada vez que se usa una instancia de una clase derivada donde se puede utilizar una instancia de la clase
base. En casi todos los lenguajes de POO est permitido lo que sigue 40 :
UnaFigura := UnaElipse;

ya que cElipse es una clase descendiente de cFigura. Tambin vimos el concepto de objeto
polimorfo, por el cual si tenemos un subprograma con el siguiente encabezado:
procedure P (X:cFigura);

Podemos invocarlo as:


P(UnaElipse);

En estos casos decimos que se est haciendo un moldeo automtico o implcito, pues no hace falta
especificarle al lenguaje que se quiere hacer una transformacin de tipos. Tambin se lo llama moldeo hacia
arriba, porque se est transformando el valor llevndolo hacia una clase que est ms arriba que la propia en la
jerarqua.
Ntese que en cuanto a los atributos y mtodos, en estos casos el objeto de la clase ancestro (el que
figura a la izquierda en la asignacin o es el parmetro del mtodo) slo podr luego usar los que tiene
declarados en su propia declaracin de clase.
Sin embargo, hay casos en los cuales puede ser necesario hacer un moldeo hacia abajo, lo cual de
ninguna manera es automtico. Por ejemplo, si necesito asignar a una variable de clase cElipse un valor de tipo
cFigura, no es una operacin que se haga en forma automtica, y debe hacerse en forma explcita, como
muestra el siguiente fragmento de cdigo Pascal:
UnaElipse := cElipse(UnaFigura);
40

La notacin es de Object Pascal.

- 57 -

CARLOS FONTELA

Este tipo de moldeo es ms peligroso, pues podran quedar valores de atributos no inicializados. Por
eso, la mayor parte de los lenguajes tienen algn mecanismo para hacer una verificacin en tiempo de ejecucin
de modo que esto no ocurra.
Para qu puede usarse el moldeo explcito? Un caso interesante es el de tener que acceder a un
atributo o mtodo que estuviera declarado en la clase descendiente desde un objeto en la ancestro. El siguiente
ejemplo ilustra esto:
UnaFigura := UnaElipse;
(UnaFigura as cElipse).Dibujar; { usa el Dibujar de cElipse }

Ntese que esto no sera correcto sin la primera lnea, pues el mtodo Dibujar de cElipse podra
intentar acceder a atributos que estn declarados en cElipse y no en cFigura, lo cual podra conducir a errores
impredecibles. Por eso, el moldeo hacia abajo debe hacerse siempre sobre objetos que en realidad sean de la
clase descendiente, aunque por alguna razn estn asignados a una variable de la clase ancestro.
En este punto hace falta una aclaracin. Para que lo anterior sea estrictamente cierto deberamos
garantizar que la lnea
UnaFigura := UnaElipse;

permita guardar la informacin completa de la elipse sin perder parte de su estado. Esto es cierto
solamente en los lenguajes en los cuales el modelo de memoria de objetos trabaja sobre referencias, como Java
y Object Pascal. Si, en cambio, el modelo de memoria implementa los objetos sobre memoria esttica, la nica
forma de garantizar esto es usando punteros, como muestra el siguiente fragmento de cdigo C++:
PUnaFigura = *UnaElipse; // es una asignacin de punteros
(cElipse)(*PUnaFigura).Dibujar; // usa el Dibujar de cElipse

No obstante, sigue pareciendo un uso raro. Por qu hara falta hacer la asignacin de la primera
lnea, en vez de trabajar directamente con una variable de tipo cElipse? La respuesta ms convincente la
encontraremos en el siguiente tem.
Datos estructurados con elementos de varios tipos
Hay un caso particular de objeto polimorfo que es el elemento de una coleccin de referencias. En
los lenguajes que implementan los objetos como referencias, si se declara un arreglo cuyos elementos son de
tipo cFigura, se les podr asignar elementos de diferentes clases descendientes de cFigura.
Esto se debe a la posibilidad de asignar a un objeto una instancia de una clase descendiente, que hace
posible construir datos estructurados cuyos elementos no sean todos del mismo tipo, sino que pertenezcan a una
familia de clases.
Por ejemplo, las declaraciones siguientes en Object Pascal:
type ArregloLibre = array [1..3] of cFigura;
var V : ArregloLibre;

permitiran en el bloque de cdigo en que se hayan declarado, las siguientes acciones:


V[1] := UnaElipse;
V[2] := UnCirculo;
V[3] := UnTrianguloRectangulo;

Aun cuando el lenguaje, como C++, implemente los objetos en memoria esttica, siempre se puede
declarar una referencia a un objeto, por lo que un arreglo de punteros a elementos cFigura podr llenarse con
punteros a cElipse, cCuadrilatero y dems.
En lenguajes en los cuales hay una clase por defecto que es ancestro ltimo de toda la jerarqua,
como Java y Object Pascal, este concepto puede ser llevado an ms all, pues el uso de estructuras cuyos
elementos son Object (en Java) o TObject (en Object Pascal), nos permite trabajar con estructuras totalmente

- 58 -

PROGRAMACIN ORIENTADA A OBJETOS

genricas. Java lo aprovecha especialmente en las bibliotecas de clases que provee al programador. El siguiente
ejemplo lo muestra:
List v = new ArrayList(); // un arreglo de elementos Object
v.add(new cElipse(0,0)); // le agrego un elemento de clase cElipse
v.add(new cCirculo(0,0)); // le agrego un elemento de clase cCirculo
v.add(new Integer(-8));
// le agrego un elemento de clase Integer
v.add(new ArrayList(1)); // le agrego un elemento de clase ArrayList

En estos casos, el moldeo hacia abajo puede ser ms necesario. Verbigracia, en el ejemplo anterior,
podra querer invocar a un mtodo propio de la clase cElipse para el primer elemento del arreglo:
(v.get(0)).Dibujar(); // incorrecto

v.get(0) obtiene el primer elemento del arreglo. Pero como es una elipse, pretendo dibujarla. Ahora
bien, v es un arreglo de elementos Object, por lo cual no puedo invocar con un elemento del arreglo el mtodo
Dibujar, propio de una clase descendiente. Por lo tanto, la lnea de ms arriba debi escribirse, moldeando el
elemento a cElipse:
((cElipse)(v.get(0))).Dibujar();

Ahora bien, para poder hacer esto habra que estar seguro de que el tipo del primer elemento del
arreglo es una elipse, lo cual podra no saberse si el bloque en el cual se est escribiendo la lnea anterior no
est en el mismo mbito en el cual se llen el arreglo v.
Para resolver este problema necesitamos poder evaluar el tipo del dato de cada elemento en tiempo
de ejecucin. Esto lo veremos en el tem que sigue.
Informacin de tipos en tiempo de ejecucin
En muchos lenguajes se puede preguntar por el tipo de datos de un objeto en tiempo de ejecucin,
aunque la sintaxis es diferente en cada caso. Pero lo que importa es que esto nos da un grado de seguridad
mayor al hacer el moldeo.
Por ejemplo, el moldeo a cElipse que mostramos en el tem anterior debera haberse escrito:
if (v.get(0) instanceof cElipse)
(cElipse)(v.get(0)).Dibujar();

La primera lnea chequea que el primer elemento de v sea una instancia de la clase cElipse antes de
efectuar el agregado de un elemento en la segunda lnea.
Es fcil abusar de esto. Por ejemplo, supongamos que se quiere escribir en Object Pascal un mtodo
que dibuje todos los elementos de un arreglo de elementos cFigura. Una primera idea podra ser:
procedure cVectorFiguras.DibujarTodas;
var I : Word;
begin
for I := 1 to CantFiguras do
if Vector[I] is cElipse
then (Vector[I] as cElipse).Dibujar
else if Vector[I] is cCuadrilatero
then (Vector[I] as cCuadrilatero).Dibujar
else if Vector[I] is cTriangulo
then (Vector[I] as cTriangulo).Dibujar
else (Vector[I] as cOtros).Dibujar
end;

- 59 -

CARLOS FONTELA

Esta solucin, adems de ser bastante poco elegante y extensa, tiene el inconveniente de que limita
seriamente la extensibilidad. Qu ocurrira si quien adquiere estas clases desea agregar una clase cPentagono
descendiente de cFigura? Podra pensarse que debera modificar cVectorFiguras.DibujarTodas. Pero esto sera
un grueso error, pues ese mtodo es parte de la biblioteca que adquiri, y presumimos que se encuentra
compilada.
La respuesta es la tradicional vinculacin tarda. Si el mtodo Dibujar es virtual, el mtodo
DibujarTodas de arriba se escribir:
procedure cVectorFiguras.DibujarTodas;
var I : Word;
begin
for I := 1 to CantFiguras do
Vector[I].Dibujar;
end;

Ntese que para cada Vector[I] se est utilizando el mtodo Dibujar que corresponda a la clase del
elemento. De esta manera no se comprometer la extensibilidad y la solucin es bastante ms limpia.

IMPLEMENTACIN DEL POLIMORFISMO EN DISTINTOS LENGUAJES


Polimorfismo y otros aspectos en Object Pascal
En Object Pascal la redefinicin se hace simplemente reescribiendo el mtodo en cuestin en la clase
derivada. La sola declaracin de un mtodo del mismo nombre que otro de la clase ancestro provoca su
ocultamiento. Si se desea sobrecargar el mtodo de la clase ancestro debe declararse explcitamente con la
directiva overload.
Los mtodos virtuales se deben declarar explcitamente, con las siguientes reglas:
?? En la primera clase en la cual se declara un mtodo virtual, viniendo de arriba hacia abajo en
la jerarqua, se hace poniendo las palabras virtual o dynamic41 a continuacin de la declaracin
del encabezado del mtodo.
?? En las clases subsiguientes de la jerarqua se coloca la palabra override.
Por ejemplo, en la clase cFigura, el mtodo Dibujar se encabezara:
procedure Dibujar; virtual; { puede usarse dynamic }

Mientras en cElipse y cCirculo sera:


procedure Dibujar; override;

Las clases abstractas no estn implementadas en Object Pascal. Es ms, ni siquiera es como en otros
lenguajes en que una clase con mtodos abstractos no puede instanciarse42 .
Los mtodos abstractos s se pueden implementar con el agregado de la directiva abstract:
procedure Dibujar; virtual; abstract;

El moldeo de clases se puede hacer como se haca para los tipos tradicionales en Pascal, como en:
cElipse(UnaFigura).Dibujar;

Sin embargo, en este caso no se va a verificar que el objeto almacenado en UnaFigura sea realmente
41

virtual significa que la implementacin va a optimizar los tiempos de ejecucin, mientras que con dynamic buscar minimizar el uso
de memoria. Por lo dems, la semntica es la misma.
42
Aunque el compilador Delphi lanza una advertencia si se la instancia.

- 60 -

PROGRAMACIN ORIENTADA A OBJETOS

una elipse. Para evitar este inconveniente se puede utilizar el operador as:
(UnaFigura as cElipse).Dibujar;

La informacin sobre el tipo se puede obtener con el operador is:


if UnaFigura is cElipse
then (UnaFigura as cElipse).Dibujar;

Object Pascal brinda algunas herramientas para trabajar con informacin sobre tipos de objetos en
tiempo de ejecucin. Por ejemplo, implementa el concepto de reflejado, que permite conocer tipos de objetos o
de sus ancestros, que no tienen significado en tiempo de compilacin, por ejemplo, porque las clases se reciben
en tiempo de ejecucin a travs de una red. Estos son conceptos muy importantes para permitir el uso de
componentes distribuidos, invocacin remota de mtodos y otros.
Polimorfismo y otros aspectos en C++
En C++ la redefinicin se hace simplemente reescribiendo el mtodo en cuestin en la clase
derivada. Sin embargo, para evitar la sobrecarga y efectivamente lograr el ocultamiento del mtodo de la clase
ancestro, el mtodo deber mantener la misma cantidad y el mismo tipo de parmetros del de la clase ancestro.
Los mtodos virtuales se deben declarar explcitamente, colocando virtual antes del nombre en la
declaracin del mtodo, como en el ejemplo:
virtual void dibujar ();

Esto se hace nicamente en la clase ms alta de la jerarqua donde aparezca el mtodo. En las clases
descendientes el mtodo ser virtual por definicin.
Los mtodos abstractos son llamados funciones virtuales puras. Como su nombre lo indica, un
mtodo abstracto es siempre virtual. Se declaran como en el ejemplo:
virtual void dibujar () = 0;

y luego no se implementan.
Las clases abstractas son aquellas que contienen mtodos abstractos. Como corolario, no hay forma
de definir clases abstractas sin declarar un mtodo abstracto en ellas, ni hay forma de declarar mtodos
abstractos en clases que no sean abstrac tas.
El moldeo de clases se puede hacer como en C:
((cElipse)UnaFigura).Dibujar();

Pero as no se verifica que el objeto almacenado en UnaFigura sea realmente una elipse. Si se quiere
hacer un moldeo ms seguro se puede obtener informacin sobre la clase del objeto utilizando el operador
typeid, que funciona cuando comparamos clases de la misma jerarqua y las clases poseen algn mtodo virtual.
Todo esto es muy restrictivo.
Afortunadamente, hay otro mecanismo, mediante el moldeo dinmico, que adems es seguro y
funciona independientemente de la jerarqua. La transformacin anterior se escribira as:
if (dynamic_cast<cElipse*>(UnaFigura) != null)
dynamic_cast<cElipse*>(UnaFigura).Dibujar();

Ntese que la misma funcin dynamic_cast sirve para hacer el moldeo (segunda lnea) como para
verificar que la transformacin sea vlida, ya que si no lo es la funcin devuelve null.
Lamentablemente, el moldeo dinmico es ms ineficiente que el uso de typeid, por lo que muchos
programadores se inclinan por esta forma me nos segura.

- 61 -

CARLOS FONTELA

Polimorfismo y otros aspectos en Java


En Java la redefinicin se hace simplemente reescribiendo el mtodo en cuestin en la clase
derivada. Sin embargo, para evitar la sobrecarga y efectivamente lograr el ocultamiento del mtodo de la clase
ancestro, el mtodo deber mantener la misma cantidad y el mismo tipo de parmetros del mtodo de la clase
ancestro.
Todos los mtodos son virtuales porque todo en Java se hace con vinculacin dinmica, salvo que el
mtodo se declare especficamente con la palabra final o sea privado (recordar que los mtodos privados no
pueden redefinirse).
Los mtodos abstractos se especifican anteponindoles la palabra abstract. Se declaran como en el
ejemplo:
abstract public void dibujar ();

y no se implementan.
Si una clase contiene uno o ms mtodos abstractos ser abstracta.
Pero las clases abstractas tambin pueden definirse sin mtodos abstractos, simplemente
anteponindoles la palabra abstract. Esto tiene bastante sentido en el caso de que se cree una clase solamente
para agrupar otras o para generalizar estructura y comportamiento no abstracto. Vale decir, no siempre tengo
mtodos abstractos en una clase abstracta. El ejemplo que sigue muestra una clase abstracta:
abstract class cFigura {
// declaraciones de atributos y mtodos
}

Cualquier clase que implemente una interfaz debera implementar todos sus mtodos para dejar de
ser abstracta.
El moldeo de clases se puede hacer como en C:
(cElipse)UnaFigura.Dibujar();

La diferencia fundamental es que Java hace una verificacin que asegure que el objeto almacenado
en UnaFigura sea realmente una elipse.
La informacin sobre el tipo se puede realizar con el operador instanceof:
if (UnaFigura instanceof cElipse)
(cElipse)UnaFigura.Dibujar();

Una forma ms precisa de hacer esto ltimo 43 (aunque parezca menos clara) es:
if UnaFigura.getClass() == cElipse.class
(cElipse)UnaFigura.Dibujar();

Java brinda notables herramientas para trabajar con informacin sobre tipos de objetos en tiempo de
ejecucin. Por ejemplo, existen mtodos que permiten conocer los mtodos y atributos que tiene una
determinada clase, as como su clase ancestro y las interfaces que implementa. Incluso implementa el concepto
de reflejado, que permite conocer tipos de objetos que no tienen significado en tiempo de compilacin, por
ejemplo, porque las clases se reciben en tiempo de ejecucin a travs de una red. Estos son conceptos muy
importantes para permitir el uso de componentes distribuidos, invocacin remota de mtodos y otros.
43

Usando instanceof me aseguro de que UnaFigura es de clase cElipse o algn descendiente. Usando getClass y el atributo class puedo
asegurar que UnaFigura es exactamente de tipo cElipse.

- 62 -

PROGRAMACIN ORIENTADA A OBJETOS

EJERCICIO RESUELTO: PROPIEDADES DE UNA INMOBILIARIA


Enunciado
Escribir clases para manejar las propiedades en venta de una inmobiliaria: casas, departamentos y
terrenos baldos. Debe haber subprogramas que calculen la comisin del vendedor a partir del precio de venta,
sabiendo que ste tiene frmulas de clculo distintas para casas, departamentos y terrenos. La unidad debe ser
autosuficiente y estar correctamente modularizada.
Solucin en Object Pascal
Ver apndice A: Propiedades de una inmobiliaria
Solucin en C++
Ver apndice B: Propiedades de una inmobiliaria
Solucin en Java
Ver apndice C: Propiedades de una inmobiliaria

EJERCICIO RESUELTO: USO DE LA IMPLEMENTACIN DE LA INMOBILIARIA


Enunciado
Escribir un subprograma que, utilizando la implementacin de la unidad del ejercicio anterior,
compare dos propiedades (que podrn ser casas, departamentos o terrenos baldos) e imprima los datos de la de
mayor precio de venta.
Solucin en Object Pascal
Ver apndice A: Uso de la implementacin de la inmobiliaria
Solucin en C++
Ver apndice B: Uso de la implementacin de la inmobiliaria
Solucin en Java
Ver apndice C: Uso de la implementacin de la inmobiliaria

- 63 -

CARLOS FONTELA

6. DOCUMENTANDO LA PROGRAMACIN
DOCUMENTACIN EN GENERAL
En general se habla mucho de la documentacin, pero no se la hace, no se le asigna presupuesto, no
se la mantiene y casi nunca est al da en los proyectos de desarrollo de software. Lo importante es la
disponibilidad de la documentacin que se necesita en el momento en que se la necesita.
Muchas veces se hace porque hay que hacerla y se escribe, con pocas ganas, largos textos, a la vez
que se est convencido de estar haciendo un trabajo intil. A veces se peca por exceso y otras por defecto.
Ocurre mucho en la Web y con productos RAD. En ocasiones se olvida que el mantenimiento tambin debe
llegar a la documentacin.
La documentacin para desarrolladores es aqulla que se utiliza para el propio desarrollo del
producto y, sobre todo, para su mantenimiento futuro. Se documenta para comunicar estructura y
comportamiento del sistema o de sus partes, para visualizar y controlar la arquitectura del sistema, para
comprender mejor el mismo y para controlar el riesgo, entre otras cosas. Obviamente, cuanto ms complejo es
el sistema, ms importante es la documentacin.
En este sentido, todas las fases de un desarrollo deben documentarse: requerimientos, anlisis,
diseo, programacin, pruebas, etc.. Una herramienta muy til en este sentido es una notacin estndar de
modelado, de modo que mediante ciertos diagramas se puedan comunicar ideas entre grupos de trabajo.
Hay decenas de notaciones, tanto estructuradas como orientadas a objetos. Un caso particular es el de
UML, que analizamos en otra obra. De todas maneras, los diagramas son muy tiles, pero siempre y cuando se
mantengan actualizados, por lo que ms vale calidad que cantidad.
La documentacin para desarrolladores a menudo es llamada modelo, pues es una simplificacin de
la realidad para comprender mejor el sistema como un todo.
Otro aspecto a tener en cuenta cuando se documenta o modela, es el del nivel de detalle. As como
cuando construimos planos de un edificio podemos hacer planos generales, de arquitectura, de instalaciones y
dems, tambin al documentar el software debemos cuidar el nivel de detalle y hacer diagramas diferentes en
funcin del usuario de la documentacin, concentrndonos en un aspecto a la vez.
De toda la documentacin para los desarrolladores, nos interesa especialmente en esta obra aquella
que se utiliza para documentar la programacin.
Para ver un anlisis ms completo de la documentacin, recomiendo el apunte que he escrito con
Pablo Surez, que se puede descargar de http://www.fi.uba.ar/materias/7507F/.

UML PARA DOCUMENTAR LA PROGRAMACIN


Una de las tantas formas de documentar la programacin consiste en utilizar diagramas que muestren
en forma grfica distintos aspectos de la aplicacin.
UML
Como la falta de un estndar que fijara el camino para la modelizacin de software orientado a
objetos creaba confusin entre los desarrolladores, entre 1994 y 1995, Booch, Rumbaugh y Jacobson ? tres de
los ms reconocidos metodologistas? decidieron unirse a Rational Software Corporation para tratar de
elaborar ese estndar. La idea fue rescatar las caractersticas ms convenientes de cada una de las corrientes
disponibles, unificarlas y extenderlas bajo el nombre de UML (Unified Modeling Language). La versin 1.0 de

- 64 -

PROGRAMACIN ORIENTADA A OBJETOS

UML fue liberada al mercado y aprobada por el OMG (Object Management Group) en 1997.
UML es un lenguaje para la visualizacin, especificacin y documentacin de sistemas, por lo que
resulta independiente del modelo de proceso que se utilice para el desarrollo de los mismos (cascada, iterativo,
con prototipos, etc.). No es un mtodo sino una notacin, pues no especifica un proceso; lo que hace es
describir el resultado de alguna etapa del desarrollo de un sistema mediante una serie de diagramas.
La idea general de UML, as como de todas las notaciones de modelado orientadas a objetos, es
centrarse ms en los objetos que en los procesos o algoritmos.
Para describir los distintos aspectos de los sistemas, de modo de mostrar diferentes perspectivas44 ,
UML define 9 tipos de diagramas:
?? Diagramas de casos de uso: representan las funciones del sistema desde el punto de vista del
usuario, y algunos comportamientos fundame ntales del sistema, aunque sean invisibles para el
cliente normal.
?? Diagramas de clases: representan la estructura esttica en trminos de clases, interfaces y
colaboraciones, y las relaciones entre ellas.
?? Diagramas de componentes: representan componentes de software.
?? Diagramas de despliegue: son un caso particular de diagrama de clases que representan los
nodos de procesamiento en tiempo de ejecucin y los componentes que residen en ellos. Es el
diagrama ms apropiado para documentar los componentes de hardware, como procesadores y
dispositivos 45 .
?? Diagramas de objetos: modelan las instancias de los elementos de un diagrama de clases,
mostrando un conjunto de objetos en un momento concreto, con sus estados y relaciones.
?? Diagramas de secuencia: son una representacin temporal de los objetos y sus interacciones.
Junto con los diagramas de colaboracin se denominan diagramas de interaccin.
?? Diagramas de colaboracin: como los diagramas de secuencia, representan objetos e
interacciones, pero no tanto en forma temporal como privilegiando las relaciones entre los
distintos objetos. Junto con los diagramas de secuencia se denominan diagramas de
interaccin.
?? Diagramas de estados y transiciones: representa el comportamiento dinmico de un objeto en
trminos de estados, transiciones y eventos.
?? Diagramas de actividades: resalta el flujo de control entre objetos, pudindose aplicar a una
operacin o a todo un sistema. Es como un diagrama de interaccin, pero centrado en las
actividades y no en los objetos. Se suele aplicar tambin al modelado de las partes no
informticas de un sistema.
UML puede ser tan sencillo o complejo como se quiera. Los creadores de la notacin, si bien afirman
que todo lo que puede conceptualizarse puede ser representado con UML, para enfatizar la variedad del
lenguaje, tambin afirman que el 80% de la mayora de los sistemas se puede modelar con el 20% de las
construcciones de UML [18].
Tambin hay que tener en cuenta que es un lenguaje de comunicacin entre humanos 46 , por lo que no
tiene sentido elaborar diagramas muy complejos si nadie los va a entender.
44

La idea de las perspectivas diferentes puede verse con una analoga con la construccin de edificios. En estos casos, un plano de
arquitectura, una vista general, un plano de instalaciones sanitarias, un plano estructural, etc., todos se refieren al mismo edificio, pero
muestran aspectos diferentes, probablemente dirigidos a personas diferentes.
45
De todas maneras, slo son necesarios en sistemas en los que el hardware sea importante. No tiene sentido hacer un diagrama de
despliegue de un sistema que va a correr en una mquina aislada. Tal vez los mejores usos de los diagramas de despliegue se den en
sistemas empotrados, sistemas cliente-servidor y sistemas distribuidos.
46
Adems de poder usarse entre humanos y mquinas.

- 65 -

CARLOS FONTELA

En este curso vamos a estudiar superficialmente los diagramas de clases, de secuencia, de estados y
de actividades, para aplicarlos a los problemas que nos ocupan.
Otros diagramas muy importantes son los de casos de uso, pero se usan ms bien en las fases de
requerimientos y anlisis.
Diagramas de clases
Los diagramas de clases representan relaciones estticas entre clases, interfaces y colaboraciones47 .
Decimos estticas en el sentido de que son rela ciones que no cambian a travs del tiempo. Entre ellas, se
representan especialmente las asociaciones entre clases (que representan cmo se relaciona una clase con otra a
travs del uso) y las relaciones de herencia o implementacin de interfaces. Tambin se muestran los atributos,
la funcionalidad y las restricciones de acceso.
Una clase se representa con un rectngulo con tres divisiones: una para el nombre de la clase, otra
para atributos y otra para los mtodos. En ocasiones no usamos las tres divisiones, sino slo dos (eliminando
los atributos) o una (slo con el nombre de la clase). Los atributos y mtodos privados se pueden indicar
precedidos de un signo -, los pblicos del signo + y los protegidos de #. Un atributo derivado48 se puede
representar precedido de una barra (/). Un atributo de clase y un mtodo de clase se pueden representar
subrayados. Las restricciones de un atributo respecto de otro u otros se pueden representar colocando la
ecuacin entre llaves, como: {superficie = lado*lado}.
A continuacin hay una clase de ejemplo:

cVentana
-Posicion : Object
-ColorFondo : int
-Ancho : int
-Alto : int
-/ Superficie : long
-Titulo : String
#Owner : cVentana
+Mover()
+Dibujar()
+Borrar()

En general no se indican las operaciones que dan valores a los atributos o que los obtienen, pues se
las supone siempre existentes. Tampoco se suelen representar constructores o destructores.
Como se ve en el ejemplo, los atributos y los mtodos se describen con la notacin de algn lenguaje
de programacin. Aqu se ha elegido la sintaxis de Java. De todas maneras, es conveniente no utilizar aspectos
de la sintaxis que tengan un significado slo en un determinado lenguaje.
A menudo se suelen indicar las responsabilidades de la clase que se diagrama. Se entiende por
responsabilidad al contrato u obligacin de la clase, en el sentido que le da la metodologa de las tarjetas
CRC49 . Es una buena prctica indicar las responsabilidades en un diagrama de clases de alto nivel. Para hacerlo,
se introduce una nueva divisin en el rectngulo que representa la clase, con el ttulo Responsabilidades, y cada
una de las mismas precedida de un signo - -.
Las asociaciones entre clases se representan con lneas rectas, sobre las cuales se puede escribir un
texto descriptivo o rol de la relacin, as como el grado de multiplicidad, como se muestra en el diagrama que
sigue:
47

El concepto de colaboracin lo veremos en un captulo prximo, y no lo diagramaremos.


Aqul cuyo valor depende del de otros atributos.
49
Las tarjetas CRC se usan para el modelado de clases en las primeras fases del desarrollo.
48

- 66 -

PROGRAMACIN ORIENTADA A OBJETOS

cPedido

cCliente
*

+Artculos de lnea

CLineaDePedido

Los grados de multiplicidad vlidos son:


Grado de Multiplicidad
1
0..1
M..N (indicando M y N como nmeros)
*
0..*
1..*
M..*

Significado
Uno y slo uno
Cero o uno
De M a N (enteros naturales)
De 0 a muchos
De 0 a muchos (igual a *)
De 1 a muchos
De M a muchos

Las relaciones de herencia se representan como un rbol, con lneas rectas, con una flecha que apunta
hacia la clase ancestro. Cuando slo se representan jerarquas y las clases ancestros se encuentran siempre ms
arriba que las descendientes, la flecha puede omitirse (as hicimos en el captulo en que introdujimos el
concepto de herencia).
A continuacin se muestra una jerarqua de clases:
cCuenta
+Depositar()
+Retirar()

cCajaAhorro

cCuentaCorriente

+Depositar()
+Retirar()

cCAComun
+Depositar()
+Retirar()

+Depositar()
+Retirar()

cCAEspecial
+Depositar()
+Retirar()

- 67 -

CARLOS FONTELA

Una clase abstracta se representa en cursiva, y lo mismo ocurre con los mtodos abstractos, como se
muestra en la jerarqua anterior con las clases cCuenta y cCajaAhorro y los mtodos Depositar y Retirar en
estas clases.
UML supone que todos los mtodos son virtuales, por lo que se debera especificar los mtodos no
virtuales con la propiedad etiquetada {leaf}. Sin embargo, no haremos esta distincin en nuestros diagramas.
Las interfaces se representan con el estereotipo <<interface>>. La implementacin de una interfaz
por una clase puede representarse como la herencia, aunque con lnea punteada50 . A continuacin se muestra la
jerarqua anterior, a la cual se le agrega la interfaz iPersistente :
interface
iPersistente
+Guardar()
+Recuperar()

cCuenta
+Depositar()
+Retirar()

cCajaAhorro

cCuentaCorriente

+Depositar()
+Retirar()

+Depositar()
+Retirar()

cCAComun

cCAEspecial

+Depositar()
+Retirar()

+Depositar()
+Retirar()

Para expresar la composicin se hace con un rombo relleno del lado de la entidad mayor, como
muestra la figura que sigue.
cPoligono

cPunto
1

La agregacin tambin puede representarse, colocando un rombo vaco en vez de relleno. Sin
embargo, en general no se la representa pues, como ya dijimos, equivale a una simple asociacin.
A veces hay atributos y comportamiento propios de las asociaciones, y en esos casos conviene crear
clases para las mismas, llamadas clases de asociacin:
50

Esta forma es denominada forma cannica de representacin de interfaces. Si no se requiere demasiada informacin de la interfaz, se
la puede representar en la forma abreviada, que es un crculo pequeo y vaco.

- 68 -

PROGRAMACIN ORIENTADA A OBJETOS

cPersona

0..1

cEmpresa

cEmpleo
aPeriodo : Date

Estas tcnicas se utilizan sobre todo en asociaciones mltiples. En las asociaciones 1 a 1 no son
necesarias porque se pueden desplazar los atributos y mtodos de la asociacin a una de las clases.
Abajo hay otra forma de representar este concepto:
*

0..1

cPersona

cEmpleo

-/ Empleador

cEmpresa

-aPeriodo : Date
1

0..1

Se pueden utilizar diagramas de clases para representar tipo de datos que no sean clases. Por ejemplo,
el siguiente diagrama representa un tipo enumerado con el estereotipo <<enumeration>>:
enumeration
tDiasLaborables
-lunes
-martes
-miercoles
-jueves
-viernes

Finalmente, debe tenerse en cuenta para los diagramas de clases:


?? No es necesario representar todas las clases con todos sus detalles, sino slo lo que sea
necesario.
?? En general, conviene representar clases, asociaciones, atributos y generalizacin. La
visibilidad, las asociaciones mltiples y otras propiedades son necesarias slo en algunas
ocasiones especiales.
?? Convie ne dibujar modelos slo de las partes importantes del sistema y mantenerlos siempre
actualizados entre prototipos y versiones.
?? Son herramientas, por lo que el grado de detalle hay que manejarlo desde el punto de vista de
la practicidad.
?? No hay que representar las clases de apoyo. Por ejemplo, si para resolver un problema de
simulacin necesito, como herramienta matemtica, un vector de posicionamiento en 3
dimensiones, esto no debera figurar porque no hace al espacio del problema.
?? Conviene ordenar los elementos del diagrama para minimizar el cruce de lneas.
?? Conviene ordenar los elementos del diagrama para que las cosas que son cercanas
semnticamente queden cerca fsicamente.
?? Conviene usar colores o seales visuales para sealar caractersticas importantes del diagrama.

- 69 -

CARLOS FONTELA

?? Los diagramas de clases deben tender a mostrar no ms de un tipo de relacin en forma


preponderante. As, se harn diagramas que enfaticen las relaciones de herencia separados de
aqullos que enfaticen asociaciones o colaboraciones.
Diagramas de secuencia
Los diagramas de secuencia son modelos dinmicos que describen cmo colabora un grupo de
objetos en un determinado escenario51 a travs del tiempo. En ellos se representan objetos y no clases.
En UML el nombre de objeto se subraya. Si no se conociese el nombre de un objeto pero s la clase a
la que pertenece, se puede representar con dos puntos seguido del nombre de clase, subrayado. Otras veces se
puede escribir tanto el nombre del objeto como el de la clase.
En el diagrama de secuencia, un objeto se representa como un rectngulo arriba de su lnea de vida.
Los mensajes son flechas entre objetos y el orden de los mensajes est dado por el eje vertical, que se lee de
arriba hacia abajo. De los mensajes se escribe, por lo menos, el nombre, aunque tambin se pueden agregar los
parmetros e informacin de control: iteraciones, condiciones, etc.. A continuacin se muestra un diagrama de
secuencia de un pedido de saldo en un cajero automtico:

Usuario XX

Cajero YY

DatosUsuarios

DatosCuentas

IngresaTarjeta()

VerificarTarjeta()
PedirClave()
ChequearUsuario (Tarjeta,Clave)()

<<create>> InicioTransaccion (Usuario)()


Transacc ZZ
MostrarMenu()

PedirSaldo()
PedirSaldo(Usuario)()
Grabar()
PedirSaldo()

Terminar()
TerminarYGrabar()

<<destroy>> TerminarYGrabar()

X
Es factible representar un mensaje enviado al mismo objeto. Tal el caso de los mensajes
51

Un escenario es un flujo de eventos simple de un caso de uso. Puede pensarse tambin como una instancia de un caso de uso.

- 70 -

PROGRAMACIN ORIENTADA A OBJETOS

VerificarTarjeta y TerminarYGrabar.
La creacin de un objeto es provocada por un mensaje enviado desde otro objeto. En el ejemplo,
Transac ZZ se crea cuando el objeto Cajero YY le enva el mensaje InicioTransaccion. Las creaciones se suelen
acompaar con el estereotipo <<create>>.
La destruccin de un objeto se puede representar por una X en la lnea de vida, y se suelen
acompaar con el estereotipo <<destroy>>. Un objeto se puede destruir a s mismo (se suicida), o puede ser
destruido por otro. En el ejemplo, el objeto Transac ZZ se suicida envindose un mensaje TerminarYGrabar.
Un mensaje asncrono (el que no espera la respuesta del objeto con el que se comunic) se representa
con una flecha de media punta, como hicimos con Grabar, Terminar y TerminarYGrabar.
Se pueden representar los retornos de los mensajes, aunque slo conviene hacerlo cuando estn
diferidos en el tiempo. Se representan igual que los mensajes, pero en lneas de puntos. As se hizo con el
retorno de PedirSaldo.
Se puede representar el hecho de que en un momento dado un objeto tiene el foco de control, con un
rectngulo a lo largo de su lnea de vida.
Como conclusin, podemos decir de los diagramas de secuencia:
?? Su gran virtud es la simplicidad y el impacto visual.
?? Ayuda a ver el flujo del control y el ordenamiento temporal de los hechos, tan difcil de seguir
en POO, y sobre todo con eventos y RAD.
?? Si se desea enfatizar ms la organizacin de los objetos que el ordenamiento temporal, se
puede usar un diagrama de colaboracin, semnticamente equivalente al de secuencia.
?? Conviene colocar ms a la izquierda los objetos ms importantes en la interaccin que se est
diagramando.
?? Ayuda a encontrar los mtodos necesarios en las clases.
?? Si un objeto enva un mensaje a otro en un diagrama de secuencia, quiere decir que sus clases
respectivas deben estar relacionadas en el diagrama de clases. Dicho de otra manera, una
asociacin en el diagrama de clases se puede materializar en un enlace en el diagrama de
secuencia, que da lugar al envo de un mensaje.
?? Como un diagrama de secuencia slo debera representar un flujo de eventos de un caso de
uso, y como estos flujos de eventos deben ser lo ms simples posible, es deseable que no haya
bifurcaciones condicionales en los diagramas de secuencia, haciendo un diagrama de
secuencia para cada caso particular. Un diagrama cmodo para expresar bifurcaciones es el
diagrama de actividades.
?? Como todo diagrama, deben ser simples: ms que mostrar toda la comple jidad de un sistema,
deben ser herramientas de fcil visualizacin.
Diagramas de estados
El diagrama de estados es un modelo dinmico que muestra los cambios de estado que sufre un
objeto a travs del tiempo. Este tiempo puede ser toda la vida del objeto, pero ms usual es representar un
objeto dentro de un caso de uso. El objeto puede ser simple o tan complejo como se quiera (hasta se puede
representar una aplicacin completa).
El diagrama de estados, por lo tanto, es una abstraccin que representa los estados, eventos y
transiciones de estados para un objeto o un sistema. Es lo que se denomina una mquina de estados, que
muestra la secuencia de estados en la vida de un objeto, los eventos que modifican estados y las acciones y
respuestas del objeto.
La representacin grfica consiste en un grafo con nodos para los estados y arcos para las
transiciones, adems de un texto en correspondencia con los arcos que identifica los eventos.
A continuacin se muestra un diagrama simple del juego del ajedrez:

- 71 -

CARLOS FONTELA

Turno de
las blancas

Juegan
las blancas

Turno de
las negras

Jaque
Ganan las negras

Juegan
las negras

Jaque
mate

Tablas

Ganan las blancas

Desde ya que este diagrama, no sirve para entender todos los estados por los que pasa el juego de
ajedrez, ni tampoco pretende cumplir este objetivo. Sin embargo, brinda una buena imagen de conjunto, por
ejemplo, para alguien que no conoce nada del juego. Siempre se puede refinar el diagrama para mostrar ms
estados y objetos.
Como se ve, los nicos componentes que deben aparecer en un diagrama de estados son los nodos y
los arcos, ms un nodo especial para indicar el comienzo y otro para indicar la finalizacin. En los nodos y los
arcos se pone una descripcin del estado o evento que corresponda.
Dentro del nodo que corresponde a cada estado se puede poner un texto adicional que especifique si
el objeto se encuentra realizando alguna accin. Asimismo, en la descripcin de las transiciones se puede poner
una condicin que se deba satisfacer, entre corchetes, o incluso parmetros que acompaen al evento.
No siempre tiene que haber un estado final. Esto ocurre, por ejemplo, en los sistemas empotrados,
que una vez instalados corren en forma continua.
Como dijimos, se trata de un diagrama sencillo. Por eso mismo, hay que tratar de que permanezca
sencillo cuidando el nivel de detalle, sin hacer diagramas muy complejos.
Para realizar un diagrama de estados:
?? Lo primero que hay que decidir es a qu eventos puede responder el objeto.
?? Hay que definir precondiciones y poscondiciones de estados inicial y final.
?? Hay que definir los estados estables.
?? Una vez realizados, se los puede probar haciendo un seguimiento de los eventos,
transiciones y estados.
Los diagramas de estados son tiles para diseadores, programadores y testers, pero debe balancearse
la informacin para que sean tiles, ya sea agrupando estados o ignorando ciertos eventos.
Son ideales en el caso en que una especificacin mediante estados sea ms ilustrativa que una que
describa actividades.
Tambin son una herramienta interesante en el caso de objetos reactivos, es decir, aquellos objetos
para los cuales la mejor forma de caracterizar su comportamiento sea sealar cul es su comportamiento frente
a estmulos provenientes desde fuera de su contexto, o aquellos que estn ociosos hasta el momento en que
reciben un evento.
Los diagramas de estado permiten tambin especificar la concurrencia de estados (veremos el
concepto de concurrencia en un captulo posterior).
Diagramas de actividades
Hemos dicho que el diagrama de actividades resalta el flujo de control entre objetos. Es, por lo tanto,

- 72 -

PROGRAMACIN ORIENTADA A OBJETOS

el menos orientado a objetos de los diagramas de UML, pues se centra en procesos.


Sin embargo, suele ser til para ver el flujo de informacin en sistemas en que este flujo es
importante. Por lo tanto, tambin es interesante para ver el paralelismo entre las tareas, aunque luego no se
programen como tareas concurrentes.
Por su naturaleza, tambin se lo suele aplicar al modelado de las partes no informticas de un
sistema, como flujos de documentos, personas y productos.
A continuacin se muestra un diagrama de actividades simplificado de la extraccin de dinero de un
cajero automtico:

- 73 -

CARLOS FONTELA

Cliente

Cajero

Inserta
tarjeta

Pide clave

Ingresa
clave

Chequea
clave

Banco

[clave incorrecta]
[clave correcta]

Pide monto
Chequea
saldo

Procesa
transaccin

Retira dinero

Entrega
dinero

[saldo >=
monto]

Debita
cuenta

[saldo <
monto]
Muestra
saldo

Retira tarjeta

Expulsa
tarjeta

- 74 -

PROGRAMACIN ORIENTADA A OBJETOS

La notacin del diagrama es bsicamente la misma que la del de estados, aunque actan varios
objetos a los que se separa en calles (del ingls, swimlanes, calles de pruebas de natacin) verticales. La
separacin de tareas en paralelo se hace mediante una barra gruesa, y lo mismo ocurre con su unin posterior.
Un rombo permite denotar ramificaciones basadas en alguna condicin.
Diagramas y programas
Como el nuestro es un curso de programacin, cabe preguntarse para qu nos sirven los diagramas
vistos respecto de la elaboracin del programa. Como resumen:
?? Los diagramas de clases son tiles para construir la jerarqua de clases y analizar asociaciones.
?? A partir de los diagramas de secuencia es fcil hacer surgir el cdigo de los mtodos ms
complejos o con mucha interaccin entre objetos.
?? Lo mismo ocurre con los diagramas de estado para objetos reactivos.
?? Y con los diagramas de actividades en el caso en que los flujos son importantes.
?? Si las interacciones son importantes, el dia grama de secuencia conviene que acompae a la
documentacin y que se mantenga actualizado.
?? Los diagramas de estados son tiles para analizar objetos que sufren muchos cambios de
estados, para modelar sistemas reactivos o para describir globalmente un sistema.
Existen herramientas que generan cdigo a partir de diagramas UML. No obstante, hay que ser
precavidos: no siempre el cdigo generado es de buena calidad, fcil de mantener y extender. Por otro lado, hay
muchas herramientas que slo generan pantallas estndar, y otras que proclaman generar cdigo y slo nos
escriben los encabezados de los mtodos que declaramos en los diagramas.
Tambin hay herramientas que generan los diagramas UML a partir de cdigo. Este proceso,
denominado ingeniera inversa, siempre es incompleta, pues el paso de un diagrama que modela la realidad a
cdigo siempre importa una prdida de riqueza de informacin. La nica forma de paliar esta prdida es
incorporar comentarios al cdigo que luego puedan ser extrados por el utilitario que hace la ingeniera inversa.

DOCUMENTACIN INTERN A
Documentacin interna de la programacin
Documentar en el propio cdigo facilita mantener la documentacin actualizada. A esto se lo llama
documentacin interna.
En otros tiempos se ponan prlogos de mdulos, se haca un buen uso de estructuras, nombres claros
y del dominio del problema y sangras que denotaban las estructuras de control. Tambin se aconsejaba dejar
los comentarios muy abundantes fuera de los prlogos para secciones muy crticas, poco claras, avisos para el
mantenimiento y efectos colaterales locales. Adems, se recomendaba no usar los comentarios como remedio
para el cdigo poco claro, sino que ante todo estaba la necesidad de que el cdigo fuera bien legible. Todas
estas recomendaciones son vlidas an hoy.
Lo que tambin hay hoy son herramientas que facilitan la documentacin interna. En Java esto es
particularmente interesante por la condicin de estndar de la herramienta. En otros casos debemos confiar en
lo que nos ofrezcan las implementaciones particulares.
El caso de javadoc
El caso de Java en cuanto a documentacin interna, como decamos, es paradigmtico, y por eso lo
analizamos aparte.

- 75 -

CARLOS FONTELA

En Java, como en cualquier otro lenguaje de programacin, se pueden escribir comentarios, de forma
tal que stos no sean tomados en cuenta por el compilador. Se pueden hacer entre un signo /* y uno */ o bien
despus de una doble barra // hasta el final de la lnea.
Pero Java utiliza una sintaxis especial para marcar elementos de documentacin interna dentro de los
comentarios, a la vez que provee una herramienta que permite extraer esa documentacin de forma que sea til
al usuario de la misma.
Esto se hace mediante el programa javadoc , que toma algunos de los comentarios que se colocan en
el cdigo con marcas especiales y construye un archivo HTML con clases, mtodos y la documentacin que
corresponde, de modo de poder verla con cualquier navegador web. Este archivo HTML tiene el mismo
formato que toda la documentacin estndar de Java.
La documentacin a ser utilizada por el programa javadoc se inscribe en comentarios que empiezan
con /** y terminan con el habitual */. Dentro de estos comentarios especiales se pueden escribir comandos para
que javadoc los interprete, siempre precedidos de @.
Se pueden documentar clases, atributos y mtodos, y siempre se debe poner la documentacin
inmediatamente antes de la declaracin respectiva. Por ejemplo:
/** documentacin de la clase */
public class cRectangulo {
/** documentacin del atributo ladoMayor */
double ladoMayor;
/** documentacin del mtodo Dibujar */
void Dibujar () { }
}

javadoc procesar la documentacin que se escriba para atributos y mtodos pblicos y protegidos,
sin emitir nada para los privados y friendly 52 , lo cual es bastante lgico porque se presume que la
documentacin es para el programador cliente y ste slo necesita lo pblico y protegido.
En cualquier lnea de documentacin para javadoc se podr agregar formatos HTML de cualquier
tipo para formatear la salida del archivo de documentacin. Slo deberan omitirse los formatos de ttulos <h1>
y <hr>, pues javadoc los utiliza para poner sus propios ttulos. Por ejemplo, el siguiente fragmento es vlido y
generar la inclusin de HTML en el documento final:
/** <h2> La clase que sigue es muy importante: </h2> */

Cuando se quiera indicar una referencia a otra clase, desde una documentacin de clase, mtodo o
atributo, se podr utilizar el comando @see:
@see nombre-de-clase
@see nombre-de-clase-con-todos-sus-calificadores
@see nombre-de-clase-con-todos-sus-calificadores#nombre-mtodo

De este modo, aparecer un vnculo del tipo vase tambin.


La informacin de versin de una clase o paquete se puede indicar con el comando @version :
@ version informacin-de-versin

La informacin a colocar puede ser cualquiera que nos parezca interesante.


52

De todas maneras, se puede incluir los atributos y mtodos privados agregando private en la lnea de comandos.

- 76 -

PROGRAMACIN ORIENTADA A OBJETOS

Con el comando @author se puede poner tambin cualquier informacin sobre el autor o autores de
una clase:
@author informacin-del-autor

Con el comando @since se puede informar desde cu ndo o qu versin se encuentra vigente una
determinada capacidad de la clase.
Para documentar parmetros, valores devueltos y excepciones 53 de un mtodo se usan los comandos
@param, @return y @throws:
@param nombre-de-parmetro descripcin
@return descripcin
@throws clase-de-excepcin-con-sus-calificadores descripcin

Tambin se pueden incluir en la documentacin avisos de supresin de una determinada


caracterstica en versiones futuras, de modo de que su uso vaya siendo abandonado, con el comando
@deprecated, que provoca un aviso del compilador.
Estndares de nomenclatura
Como ocurri siempre en la historia de la programacin, sigue siendo vlida la idea de usar
estndares de nomenclatura, de modo tal que mirando un identificador en medio del cdigo podamos
determinar si se trata de una clase, de un mtodo, etc.. Tambin deberamos poder deducir su significado.
Hay diferentes tipos de estndares que intentar lograr este propsito.
Uno de ellos es el mtodo hngaro, tal vez el ms recargado, que llega a colocar una letra como
prefijo para indicar el tipo y sufijos que indican quin es el autor. Tambin recomienda empezar algunos
nombres con _. Lamentablemente, todo esto hace que los programas no sean demasiado legibles. Suele estar
desaconsejado, y se lo pone de ejemplo de exageracin.
El estndar de nomenclatura ms usual para Java es el que sigue:
?? Para las clases, utilizar nombres extrados del vocabulario del sistema, y escribirlos en
minsculas, utilizando las maysculas al comienzo de cada palabra, como en
NumeroComplejo o TrianguloRectangulo.
?? Para las interfaces, usar las mismas convenciones que para las clases, agregando una I al
comienzo.
?? Para los atributos, se suelen utilizar nombres de propiedades de la clase a la que
pertenecen, escribindolos en minsculas, salvo para separar palabras, como en parteReal
o hipotenusa.
?? Para los mtodos, se suelen elegir verbos en infinitivo o participios, con la misma
convencin de maysculas y minsculas que para los atributos.
?? Para los objetos, se aplican los mismos criterios que para las clases, con la posibilidad de
ser ms precisos, utilizando la convencin de maysculas y minsculas de los atributos y
mtodos.
En Pascal se utiliz durante mucho tiempo un estndar que consista en escribir todo en minscula y
separar palabras con guin bajo (_). Luego, y a pesar de que el compilador Pascal no distingue, se empez a
53

El concepto de excepcin se ve en un captulo posterior.

- 77 -

CARLOS FONTELA

usar este estndar, que luego qued en Object Pascal:


?? Para los tipos y clases, utilizar nombres extrados del vocabulario del sistema, y escribirlos
en minsculas, utilizando las maysculas al comienzo de cada palabra y agregando una T
delante, como en TCanvas y TComponent.
?? Para las interfaces se usan las mismas convenciones que para las clases, pero con una I en
vez de la T.
?? Para los atributos, utilizar nombres de propiedades de la clase a la que pertenecen,
escribindolos con las mismas convenciones de las clases, sin ninguna letra inicial.
?? Para los mtodos, elegir verbos en infinitivo o participios, con la misma convencin que
para los atributos.
?? Para los objetos, la misma notacin de los mtodos y atributos en cuanto a la convencin
de maysculas y minsculas.
En nuestro caso, hemos recurrido a un estndar consistente en:
?? Para las clases, utilizar nombres extrados del vocabulario del sistema, y escribirlos en
minsculas, utilizando las maysculas al comienzo de cada palabra. Para enfatizar que se
trata de una clase, hemos agregado una c adelante, como en cComplejo.
?? En las clases de excepcin hemos reemplazado la c por una e.
?? Para las interfaces, us amos las mismas convenciones que para las clases, pero con una i
minscula en vez de la c.
?? Para los tipos que no son clases, utilizamos una t delante del nombre.
?? Para los atributos, utilizamos nombres de propiedades de la clase a la que pertenecen,
escribindolos con las mismas convenciones de las clases, salvo que la primera letra es
siempre una a.
?? Para los mtodos, elegir verbos en infinitivo o participios, con la misma convencin que
para los atributos y clases, pero sin colocar ninguna letra delante.
?? Para los objetos, aplicamos la misma notacin de los mtodos en cuanto a la convencin
de maysculas y minsculas.
Nos pareci que este estndar de nomenclatura era adecuado desde el punto de vista del cliente, que
suele tratar con objetos y mtodos ms que con clases y atributos. Asimismo, nos pareci que cumpla una
finalidad didctica mayor que los anteriores.
De todas maneras, no importa demasiado qu estndar se utilice, sino que se utilice alguno, y sobre
todo, con fundamentos y coherencia. Por otro la do, como el lenguaje que se est utilizando siempre tiene
identificadores predefinidos, habra que tratar de que nuestro propio estndar no difiera demasiado del del
lenguaje.

EJERCICIO RESUELTO: DIAGRAMAS DE ACTIVIDADES, CLASES Y SECUENCIA


Enunciado
Hacer los diagramas de actividades (a nivel de anlisis), de clases y de secuencia del proceso de
anotacin de un alumno en las materias de un postgrado. Para ello, se supondr que cada alumno podr
anotarse en varios cursos, para los cuales habr que verificar que tenga aprobadas las correlativas. En una
segunda etapa, el profesor del curso y el coordinador del postgrado evaluarn la situacin del alumno y
aprobarn o no la solicitud, dado que pueden considerar que la orientacin general que el aspirante le est
dando a sus estudios no debera orientarlo en esa direccin.

- 78 -

PROGRAMACIN ORIENTADA A OBJETOS

Solucin
Diagrama de actividades:

- 79 -

CARLOS FONTELA

Aspirante

Sistema inscripcin

Solicita ingreso sistema inscripciones

Pide datos y clave

Ingresa datos y clave

Profesor

Coordinador

Evuala situacin

Evuala situacin

Chequea clave

[clave incorrecta]
[clave correcta]

Pide inscribirse en curso


Chequea correlativas

[correlativas insuficientes]

[correlativas suficientes]

[solicitud no aprobada]

[solicitud no aprobada]

[solicitud aprobada]

Recibe rechazo

[solicitud aprobada]

Recibe aprobacin solicitud

Notifica alumno

Inscribe alumno

- 80 -

PROGRAMACIN ORIENTADA A OBJETOS

Diagrama de clases:
1

cSistemaInscripcion

cPersona
*

cCurso
+ChequearCorrelativas()
+InscribirAlumno()
*

+PantallaInscripcion()
+ElegirCurso()

cDocente

cAspirante

+ConsultarOpinion()

+NotificarAlumno()

cProfesor

+ConsultarOpinion()

cCoordinador
+ConsultarOpinion()

cCurriculaAlumno
+ConsultarCurricula()

El contorno ms grueso de clase cSistemaInscripcion indica que se trata de un objeto activo, que
puede disparar llamadas concurrentes.
Debe notarse que, cuando el sistema de inscripcin se comunica con una persona, sea sta un
aspirante o un docente, lo que hace es trabajar con un objeto cliente, que en realidad es una interfaz de usuario
que ve la persona. Reconozcamos que esta relacin fue la nica razn que justific la existencia de la clase
cPersona en el diagrama.
Diagrama de secuencia:

- 81 -

CARLOS FONTELA

unAspirante

SistemaInscripcion

unCurso

unProfesor

Coordinador

unaCurriculaAlumno

PantallaInscripcion()

ElegirCurso()
ChequearCorrelativas()

ConsultarOpinion()
ConsultarCurricula()
ConsultarOpinion()

ConsultarOpinion()
ConsultarCurricula()
ConsultarOpinion()

NotificarAlumno()

InscribirAlumno()

El contorno ms grueso del objeto SistemaInscripcion indica que se trata de un objeto activo, que
puede disparar llamadas concurrentes. Precisamente, las llamadas a los dos mtodos ConsultarOpinion se
hacen asncronas y en paralelo. Estos conceptos se estudiarn en el captulo de concurrencia.
Ntese que no todos los estados del diagrama de actividades quedaron reflejados en el diagrama de
secuencia, aunque s los principales. Tambin fue necesario introducir dos objetos nuevos, el curso y la
currcula del alumno.

EJERCICIO RESUELTO: UN DIAGRAMA DE ESTAD OS


Enunciado
Hacer el diagrama de estados - transiciones para el siguiente escenario:
a) Un reloj digital tiene un visor y dos botones, el botn A y el botn B. El reloj tiene dos modos
de operacin, mostrar hora y corregir hora.
b) En el modo mostrar hora, se muestran las horas y minutos, separados por dos puntos. El modo
corregir hora tiene dos submodos, corregir hora y corregir minutos.
c) El botn A es el usado para cambiar de modo. Cada vez que es presionado el modo avanza
secuencialmente: mostrar hora, corregir hora, corregir minutos, etc.
d) En cada submodo el botn B es usado para avanzar las horas o minutos cada vez que es
presionado. Los botones deben ser soltados antes de generar algn otro evento.

- 82 -

PROGRAMACIN ORIENTADA A OBJETOS

Solucin
Mostrando hora

[Botn A apretado]

[Botn B apretado] / Horas++


Corrigiendo horas
[Botn A apretado]

[Botn B apretado] / Minutos++


Corrigiendo minutos

- 83 -

También podría gustarte