3. ¿Qué es la programación orientada a objetos?
Orientado a objetos ha sido la expresión de moda de los últimos
años. De repente, todo el mundo la utiliza, pero con un abanico
de significados tan amplio que nadie parece saber exactamente
lo que dicen los demás. Es difícil imaginar dos lenguajes de
progrmación tan diferentes como los son Smalltalk-80 y Ada, y,
sin embargo, a veces se dice qde los dos que son orientados a
objetos. Otros piensan que los objetos son fundamentalmente una
manera de expresar la concurrencia, y aún hay quien dice que
son una forma de organizar jerárquicamente unos hechos
complejos.
¿Cómo es posible que un mismo término esté relacionado con
cosas tan distintas como los lenguajes de programación, las
interfaces de usuario, esquemas para representar el
conocimiento de los expertos, sistemas operativos
distruibuidos, sistemas de conmutación para telefonía, y muchas
más? ¿Qué es lo que significa realmente orientado a objetos?
4. ¿Qué es la programación orientada a objetos?
Más allá del entorno de las computadoras, la palabra objeto
significa algo que está bien determinado. Los lápices,
colibríes, moléculas y galaxias son objetos, pero los océanos,
la niebla, y el sarampión no son objetos.
Aunque el concepto de espacio de direcciones de una computadora
no define lo que son unos límites dien definidos, los
programadores han decidido adoptar esta palabra. Sin definir en
primer lugar los términos clave, como es “límites”, no podemos
esperar que sea posible entender el significado de una palabra
como “objeto”.
Aquí vamos a examinar varios significados del término,
describiendo la forma en que se utiliza la palabra en varios
lenguajes de programación. El objetivo no es ofrecer una
panorámica exhaustiva de todo lo que se ha hecho o se ha dicho
con el nombre de programación orientada a objetos, sino
describir unos cuantos puntos de vista clave, de entre los que
se han explorado en el espectro de posibilidades.
5. Smalltalk-80
Smalltalk-80 es un lenguaje de programación y un entorno de
programación integrados. Es el resultado de más de una década
de investigación del Software Concepts Group mantenido por
Xerox PARC (Palo Alto Research Center). Smalltalk es un sistema
notablemente influyente. No sólo ha afectado a otros productos
comerciales, como es sistema Star de ofimática y el sistema
Interlisp-D de Ingeniería del conocimiento.
Xerox Star computer system introducida en Abril 1981
Además, ha influido sobre muchos otros sistemas académicos y
comerciales
6. Smalltalk-80
Su influencia sobre muchos otros sistemas Lisa y Macintosh de
Apple es algo ampliamente aceptado, por no mencionar su efecto
sobre toda una gama de productos menos conocidos de ofimática,
autoedición y diseño asistido por computadora. Gran parte del
entusiasmo actual por las estaciones gráficas de alta
resolución, las interfaces por iconos de usuario, y las
computadoras personales, tiene unas raíces que nos llevan a la
demostración del valor y la realizabilidad de aquellas ideas.
sistema Lisa (1984)
7. Smalltalk-80
Antes, el valor de Smalltalk residía en probar conceptos que
posteriormente se explotaban en otros sistemas, y no como un
sistema de importancia comercial por derecho propio. Esto
cambió después, a medida que empezaron a estar disponibles
programas comerciales con una relación de costo razonable, y a
medida que el mercado iba descubriendo la forma en que
Smalltalk encajaba con el abanico tradicional de soluciones de
programación.
Desde un principio, los diseñadores de Smalltalk hicieron
hincapié en un cierto número de ideas innovadoras y
controvertidas sobre lo que debería ser la computación:
8. Smalltalk-80
1.- Computación personal: Las computadoras son
baratas, y las personas son caraas. No se deben compartir las
computadoras. Dar a cada persona su propia computadora
multiplicaría la potencia de cálculo disponible, y permitiría
que el rendimiento de la máquina fuera menos importante en el
diseño.
9. Smalltalk-80
2.- Interacción: El entorno de computación deberá hacer
cualquier cosa con tal de proporcionar una retroalimentación
inmediata para todas las acciones del usuario
10. Smalltalk-80
3.- Gráficos: Las personas tienen una facilidad máxima
para el pensamiento visual. El texto debe ser sustituido por
gráficos siempre que sea posible.
11. Smalltalk-80
4.- Programación orientada a objetos: Las
personas trabajan mediante conceptos de ámbitos de problemas,
mientras que el hardware funciona mediante conceptos distintos
(operadores y operandos). Parte de la carga conceptual consiste
en traducir desde el dominio del problema hasta el dominio de
la computadora, haciendo que la máquina funcione en términos de
los conceptos más conocidos del mundo habitual del usuario.
12. Smalltalk-80
Smalltalk-80 es el nombre de varias capas de abstracción que,
en conjunto, dan vida a estas afirmaciones. Desde un principio,
los diseñadores de Smalltalk-80 se inspiraron en la visión del
futuro de Alan Kay, el Dynabook. Smalltalk-80 se diseñó para
que fuese el lenguaje de programación de sistemas en máquinas
de esta potencia.
13. La máquina virtual
En Smalltalk-80, un objeto es algún dato privado, y una
colección de procedimientos que pueden acceder a esos datos.
Los datos son propiedad privada del objeto, y no es posible
acceder a ellos sin ayuda de uno de los procedimientos de ese
objeto. Los procedimientos son públicos para todos los
consumidores, que acceden al objeto mediante expresiones que
contienen mensajes.
Procedimiento Procedimiento Procedimiento
Procedimiento Procedimiento
Datos
Procedimiento privados Procedimiento
Procedimiento Procedimiento Procedimiento
14. La máquina virtual
El mensaje que contiene la expresión dice al objeto lo que debe
hacer. El objeto responde al mensaje seleccionando primero y
ejecutando después un procedimiento mediante el cual todos los
objetos de su clase ponen en práctica este mensaje. Este
procedimiento se denomina método, y la orden que lleva el
mensaje se llama selector.
Objeto
Mensaje: Objeto has esto Procedimiento Procedimiento Procedimiento
Procedimiento Procedimiento
Datos
Procedimiento privados Procedimiento
Procedimiento Procedimiento Procedimiento
15. La máquina virtual
El mensaje que contiene la expresión dice al objeto lo que debe
hacer. El objeto responde al mensaje seleccionando primero y
ejecutando después un procedimiento mediante el cual todos los
objetos de su clase ponen en práctica este mensaje. Este
procedimiento se denomina método, y la orden que lleva el
mensaje se llama selector.
Objeto
Mensaje: Objeto has esto Procedimiento Procedimiento Procedimiento
Metodo Procedimiento
Datos
Procedimiento privados Procedimiento
Procedimiento Procedimiento Procedimiento
16. La máquina virtual
El mensaje que contiene la expresión dice al objeto lo que debe
hacer. El objeto responde al mensaje seleccionando primero y
ejecutando después un procedimiento mediante el cual todos los
objetos de su clase ponen en práctica este mensaje. Este
procedimiento se denomina método, y la orden que lleva el
mensaje se llama selector.
Objeto
Procedimiento Procedimiento Procedimiento
Metodo Procedimiento
Datos
Procedimiento privados Procedimiento
Procedimiento Procedimiento Procedimiento
17. La máquina virtual
El mensaje que contiene la expresión dice al objeto lo que debe
hacer. El objeto responde al mensaje seleccionando primero y
ejecutando después un procedimiento mediante el cual todos los
objetos de su clase ponen en práctica este mensaje. Este
procedimiento se denomina método, y la orden que lleva el
mensaje se llama selector.
Objeto
Procedimiento Procedimiento Procedimiento
Metodo Procedimiento
Datos
respuesta del objeto
Procedimiento privados Procedimiento
Procedimiento Procedimiento Procedimiento
18. La máquina virtual
Smalltalk sigue exhaustivamente este principio. Absolutamente
todo son objetos: no sólo las entidades grandes y poco
utilizadas, como las ventanas, directorios y proyectos, sino
también las entidades muy utilizadas, de bajo nivel, como los
enteros y las zonas de pila. (Por supuesto, tanto en estos
casos como en otros, se lleva a cabo una potente optimización).
La ventaja es la consecuencia que se aprecia a lo largo y ancho
de todo el sistema. Todo el sistema integrado está organizado
en virtud de un único principio, de tal modo que el usuario
sólo necesita comprender este principio para explorar cualquier
parte de Smalltalk-80. Una vez que ha aprendido a utilizar el
inspector para examinar un objeto ya sabe todo lo que necesita
para inspeccionar y entender las zonas de pila, enteros,
números de punto flotante y literalmente, cualquier cosa del
sistema.
19. La máquina virtual
En este curso vamos a adoptar las definiciones de Smalltalk-80
para todos los conceptos orientados a objetos, incluyendo
objetos, mensajes, clases y métodos, y herencia.
La exepción principal es la forma en que se determina la
duración de los objetos. Smalltalk-80 proporciona una
recolección automática de basura, lo cual significa que la
duración de todos los objetos no está determinada por el
programador, sino por el sistema. Cuando ya no se hace
referencia a un objeto, su memoria se libera automáticamente
para ser reutilizada.
20. La máquina virtual
Para conseguir esta eficiencia,
y también para permitir que el
espacio libre se pueda reunir
fácilmente cuando la memoria se
fragmenta, Smalltalk asigna un
significado al concepto de
objeto. Normalmente, los objetos
se identifican directamente
mediante sus direcciones de
memoria. Pero en Smalltalk se
identifican a partir de un
offset, dentro de una tabla de
objetos, una de cuyas entradas
es la dirección en memoria del
objeto. Esto oculta la gestión
de memoria a los ojos del
programador y hace que la
gestión de direcciones sea
asunto del sistema, y le permite
que traslade las cosas cuando
sea necesaro.
21. La máquina virtual
Todas las cosas son objetos, incluso las entidades de bajo
nivel, como los enteros cortos.
Una realización típica representa a los identificadores de
objetos como enteros de 16 bits, de los cuales se emplean 15
bits para identificar directamente a los enteros cortos (esto
es, los enteros cortos no ocupan posiciones dentro de la tabla
de objetos). El otro bits se utiliza para indicar que esa
identificación no es la de un entero corto, sino un offset
dentro de la tabla de objetos.
1- Es un offset dentro
de la tabla de objetos
Número entero de 15 bits
0- No es un offset.
Es un número solamente
22. La máquina virtual
Los beneficios de la recolección automática de basura son
muchos, porque eliminan toda una clase de errores realmente
desagradables. Se elimina el problema de los punteros
colgantes,
23. La máquina virtual
Los beneficios de la recolección automática de basura son
muchos, porque eliminan toda una clase de errores realmente
desagradables. Se elimina el problema de los punteros
colgantes, consistente en que los identificadores de objetos
inexistentes (que se producen al liberar el objeto al que
apuntan) pueden permanecer en un estado de animación suspendida
durante periodos arbitrarios de tiempo, y después causan
problemas difícilmente diagnosticables (errores del sistema)
cuando, finalmente, se accede a ellos.
24. La máquina virtual
Y además se evita el problema, igualmente peligroso,
consistente en que una aplicación que se ejecute durante mucho
tiempo pueda asfixiarse por falta de memoria, como consecuencia
de no haberse liberado objetos que ya no se necesitan.
25. La máquina virtual
Pero también tiene sus inconvenientes. En combinación con el
intenso uso de mensajería ligada dinámicamente por parte de
Smalltalk, puede dar lugar a unos costos monumentales en lo que
se refiere a los recursos de la máquina, impidiendo que se
utilice Smalltalk-80 para algunas aplicaciones en que el
rendimiento es imprescindible.
Ciertamente, los recursos no se están desperdiciando, sino que
han sido invertidos deliberadamente, con objeto de trasladar un
trabajo que normalmente realizan los programadores, que cada
vez son más onerosos, a unas máquinas que cada vez son más
baratas.
26. El lenguaje de programación
La simplicidad de la máquina virtual de Smalltalk permite que
el lenguaje de programación sea también de una sencillez poco
habitual. La compleja sintaxis que ofrece la mayoría de los
lenguajes resulta completamente innecesaria, porque todo es de
un único tipo, un objeto.
Tampoco se necesitan estructuras de control, puesto que se
realizan mediante mensajería.
27. El lenguaje de programación
De hecho, el lenguaje Smalltalk sólo define la sintaxis para:
1.- Declarar nombres de
objetos, y asignarles
valores.
sintaxis para:
3.- Definir nuevas clases
2.- Enviar mensajes.
y métodos.
los dos últimos no necesitan una sintaxis especial, puesto que
se realizan órdenes dadas con el ratón al browser, una
herramienta del entorno Smalltalk-80 para leer, modificar y
compilar métodos.
28. Mensajes
El tipo más sencillo de mensajes son las expresiones que
contienen mensajes unarios. Un mensaje unario es un mensaje sin
argumentos, así que consta de dos partes nada más:
El nombre del objeto
que debe recibir el El nombre del mensaje
mensaje
cantidad sqrt
cadNombre size
29. Mensajes
un segundo tipo de mensaje son los que contienen expresiones
con palabras reservadas. Pueden tener argumentos, tantos como
partes tenga la palabra reservada. El selector de un mensaje
con palabra reservada consta de una o más palabras reservadas,
cada una de las cuales precede a un argumento. Una parte de una
palabra reservada es un identificador sencillo, seguido por dos
puntos
indice max:limite
gastosCasa gastoCantidad:540.00 porRazon:Renta
Ambos ejemplos envían un mensaje de una sola palabra reservada,
aunque el selector del segundo ejemplo esté escrito en dos
partes, separadas por el argumento 548.00.
30. Mensajes
indice max:limite
gastosCasa gastoCantidad:540.00 porRazon:Renta
La primera sentencia envía el mensaje
max:, al objeto índice
31. Mensajes
indice max:limite
gastosCasa gastoCantidad:540.00 porRazon:Renta
La primera sentencia envía el mensaje
max:, al objeto índice
Y la segunda sentencia envía el mensaje gastoCantidad:
porRazon: al objeto gastosCasa.
32. Mensajes
indice max:limite
gastosCasa gastoCantidad:540.00 porRazon:Renta
La primera sentencia envía el mensaje
max:, al objeto índice
Y la segunda sentencia envía el mensaje gastoCantidad:
porRazon: al objeto gastosCasa.
En ambos casos, los dos puntos forman parte inseparable del
selector del mensaje, y se mantienen, incluso, en
conversaciones orales. Por ejemplo, el mensaje de la segunda
línea se enuncia “gastos-casa-dospuntos-por-razón-dospuntos”.
Los dos puntos indican los lugares en que hay que suministrar
un argumento. Tanto el receptor como los argumentos pueden ser
nombres de variables, constantes u otras expresiones.
33. Mensajes
Los mensajes binarios se comportan igual que los mensajes con
palabra reservada de un solo argumento. El selector de un
mensaje binario es siempre uno o dos caracteres de un
conjuntos de caracteres especiales designados al efecto. Lo
siguiente son ejemplos de expresiones con mensajes binarios:
3+4
total-1
total<=max
Por último, se utiliza el operador de asignación para
almacenar valores en las variables:
suma:=3+4
x:=theta sin
Como las expresiones que contienen mensajes pueden estar
fuertemente anidadas dentro de otras, se ofrecen reglas de
prioridad, y se pueden utilizar los paréntesis para invalidar
las reglas de prioridad cuando sea necesario.
34. Bloques
Smalltalk es un entorno interactivo, así que las expresiones,
normalmente se evalúan de inmediato. Es posible almacenar
expresiones para su posterior ejecución, encerrándolas entre
corchetes. Esto crea una interesante estructura llamada
bloque. Un bloque es un objeto (una instancia de la clase
Block) que representa una secuencia de instrucciones cuya
ejecución debe retrasarse hasta el momento en que el bloque
reciba el mensaje value. La mayoría de las estructuras de
control de Smalltalk están realizadas como mensajes a objetos
que admiten bloques como argumentos. Por ejemplo:
indice<=limite
ifTrue:[total:=total+(lista at:indice)]
La expresión indice<=limite es un mensaje binario que enviamos
al objeto indice, y que es una instancia de alguna clase de
número.
35. Bloques
indice<=limite
ifTrue:[total:=total+(lista at:indice)]
El número crea una nueva instancia de la clase Boolean, y la
línea siguiente envía a esta variable lógica el mensaje
ifTrue: con una instancia de la clase Block como argumento.
La variable lógica evalúa el bloque enviándole el mensaje
value si el estado de la variable lógica es TRUE.
36. Bloques
indice<=limite
ifTrue:[total:=total+(lista at:indice)]
La expresión indice<=limite es un mensaje binario que enviamos
al objeto indice, y que es una instancia de alguna clase de
número.
¿Eres menor que limite?
indice<=limite indice es un Numero
37. Bloques
indice<=limite
ifTrue:[total:=total+(lista at:indice)]
El número crea una nueva instancia de la clase Boolean, y la
línea siguiente envía a esta variable lógica el mensaje
ifTrue: con una instancia de la clase Block como argumento.
La variable lógica evalúa el bloque enviándole el mensaje
value si el estado de la variable lógica es TRUE.
¿Eres menor que limite?
indice<=limite indice es un Numero
es un Boolean
ifTrue:
38. Bloques
indice<=limite
ifTrue:[total:=total+(lista at:indice)]
El número crea una nueva instancia de la clase Boolean, y la
línea siguiente envía a esta variable lógica el mensaje
ifTrue: con una instancia de la clase Block como argumento.
La variable lógica evalúa el bloque enviándole el mensaje
value si el estado de la variable lógica es TRUE.
¿Eres menor que limite?
indice<=limite indice es un Numero
es un Boolean
total:=total+(lista at:indice) ifTrue:
39. Bloques
Los bloques tienen un aspecto engañosamente sencillo. Oculta
en el interior de la breve frase, una secuencia de
instrucciones cuya ejecución debe retrasarse, se encuentran
algunas posibilidades muy potentes. Por ejemplo, aunque un
bloque se parece a una sentencia compuesta de C o a una pareja
BEGIN...END de Pascal, y aunque se utilicen frecuentemente de
esa manera, los bloques comparten pocas de las limitaciones
que imponen estos lenguajes sobre el tiempo que puede
retrasarse la ejecución.
En la mayoría de los lenguajes, la ejecución no puede
retrasarse más allá de la duración del entorno, una
restricción que se deriva de la suposición oculta consistente
en que el estado de ejecución de todo bloque de código está
contenido en una sencilla pila de hardware, que siempre crece
o disminuye por un extremo.
40. Bloques
Los bloques de Smalltalk-80 no poseen esta restricción, porque
las zonas de pila son objetos, y se reservan y liberan con
toda la generalidad que se ofrece para cualquier otro tipo de
objeto. En particular, los bloques se reservan en el heap, y
son eliminados por la colecta de basura, no cuando concluye el
entorno que los creó.
Cualquier bloque junto con el entorno en que fuera creado
originalmente (su contexto) puede ser retenido
indefinidamente, y puede ser ejecutado mucho después de que
retorne el mensaje que lo creó. Por ejemplo, lo que sigue
proporciona a unConjunto instrucciones acerca de lo que tienen
que hacer si falla la eliminación de unElemento; por ejemplo,
porque el conjunto no contiene ese elemento:
unConjunto remove:unElemento ifFail:[...]
41. Bloques
unConjunto remove:unElemento ifFail:[...]
Este bloque será ejecutado por unConjunto, y no por el que
hizo la llamada, pero, sin embargo, tendrá acceso completo al
contexto del método que hiciera la llamada, incluyendo sus
variables locales y sus argumentos. Al bloque se le da una
referencia del contexto del que hace la llamada cuando se crea
el bloque, y este contexto persiste mientras exista alguna
referencia a él en alguna parte del sistema.
Por ejemplo, está permitido almacenar referencias de bloques
en objetos de larga duración, como los menús, que sobreviven
al procedimiento que los ha creado.
42. Bloques
Esta extraordinaria posibilidad se deriva directamente de la
decisión de no hacer excepciones a la regla consistente en que
todo debe beneficiarse de toda la potencia que el sistema
proporciona para cualquier objeto, incluyendo las entidades de
bajo nivel que la mayoría de los lenguajes gestiona de forma
especial, como las zonas de pila. Los beneficios son
cuantiosos, porque este único concepto, el bloque, saca del
lenguaje un cierto número de temas difíciles, y los pone a
disposición de los usuarios. El precio también es
considerable, porque incluso las operaciones más utilizadas,
como la mensajería, no pueden beneficiarse del uso de rápidas
pilas secuenciales especializadas, y además soportan el peso
del tratamiento de la recolección de basura.
43. El entorno de programación
El lenguaje de programación,
las herramientas
complementarias (editores de
texto, enlazadores,
depuradores) y el sistema
operativo en sí, son un todo
integrado y fuertemente
acoplado, y son corresidentes
en un mismo espacio virtual
de direcciones.
44. El entorno de programación
Este entorno hace hincapié en la creatividad personal. Esto
resulta especialmente evidente en su filosofía, que es hacer
posible el acceso a todo el sistema, incluso a cosas que la
mayoría de los programadores no osaría cambiar, como el
sistema operativo, o la representación de los números de punto
flotante. Ninguna de esas cosas está protegida.
45. El entorno de programación
Todo se puede modificar de manera igualmente sencilla;
incluyendo aquellos cambios que no sean congruentes con el
resto del sistema y puedan hacerlo caer, o cambios que
pudieran hacer que el trabajo subsiguiente no fuera compatible
con el que se esté desarrollando en sistemas vecinos. De
manera que hay que tener mucho cuidado para no tener serios
problemas con el sistema.
46. El entorno de programación
La confusión que puede causar la piratería sin orden ni
concierto era evidente para los diseñadores de Smalltalk-80, y
le obligó a pensar creativamente acerca de las herramientas
necesarias para gestionar el cambio. El resultado fue un
entorno maravillosamente diseñado, para enfrentarse al cambio
de una forma cómoda y disciplinada. Los usuarios de Smalltalk
-80 trabajan en pantallas de alta resolución, utilizando una
herramienta llamada browser.
47. El entorno de programación
El browser es como un editor de textos, porque puede mostrar
el código fuente para leerlo o editarlo. También la forma
fundamental de utilizar el compilador, modificando por tanto
el sistema en su lugar.
El browser ofrece también una vía para que los miembros del
equipo se comuniquen en lo que se refiere a su software. El
entorno personal de cada programador se construye integrando
periódicamente el trabajo de todo el equipo. La persona
responsable de integrar el trabajo del equipo utiliza una
herramienta similar al browser. Va comprobando la congruencia
de cada cambio, e identifica a los objetos sospechosos para
que se les preste especial atención. Esto produce una nueva
versión del sistema base, que se distribuirá a todos los
miembros del equipo.
48. El entorno de programación
Cada una de las nuevas versiones incluye todo el código fuente
del sistema, incluyendo los comentarios, de tal modo que
integración/publicación va dando a conocer periódicamente el
trabajo de cada individuo al resto del grupo. Los miembros del
grupo pueden utilizar el browser para conocer las
contribuciones de los demás, y el browser admite estas
búsquedas con ayudas que ofrecen referencias cruzadas.
Esto equivale a un medio electrónico de publicar y estudiar el
tipo de información que la mayoría de los programadores
gestiona de forma menos eficiente empleando el papel.
49. Está claro que Smalltalk es la solución, pero, ¿cuál es el problema?
Desde un principio, el objetivo de los creadores de Smalltalk
era la investigación. La utilidad de cualquier producto
resultante, como el propio Smalltalk, era puramente
secundaria. En este aspecto tuvieron éxito porque los frutos
de su trabajo han tenido una amplia difusión. Pero, ¿qué pasa
con Smalltalk en sí? ¿Tiene su lugar más allá del entorno de
la investigación junto a los lenguajes convencionales de
programación como C, o incluso al lado de robustos dinosaurios
como COBOL o FORTRAN?
La aplicación evidente es la construcción de prototipos de
sistemas, que después volverán a codificarse en lenguajes
convencionales, y parece que a esto se reduce la mayor parte
de su utilización en la actualidad.
50. Está claro que Smalltalk es la solución, pero, ¿cuál es el problema?
Estas gigantescas bases de datos existen porque los ejecutivos
necesitan una información precisa y actualizada, sobre la cual
basarán sus decisiones. Pero se quejan por los retrasos e
incomodidades implícitos al acceder a los datos, separados
como están de ellos por varias capas de personal dedicado a
procesamiento de datos.
51. Está claro que Smalltalk es la solución, pero, ¿cuál es el problema?
Smalltalk podría muy bien tener un papel, incluso en ese mundo
de traje y corbata. Un programador de Smalltalk podría
desarrollar clases que encapsulen el conocimiento necesario
para extraer datos del entorno, y estas clases se utilizarían
para permitir que otros programadores menos experimentados
atendiesen directamente al ejecutivo.
52. Está claro que Smalltalk es la solución, pero, ¿cuál es el problema?
Smalltalk podría muy bien tener un papel, incluso en ese mundo
de traje y corbata. Un programador de Smalltalk podría
desarrollar clases que encapsulen el conocimiento necesario
para extraer datos del entorno, y estas clases se utilizarían
para permitir que otros programadores menos experimentados
atendiesen directamente al ejecutivo.
53. Está claro que Smalltalk es la solución, pero, ¿cuál es el problema?
Smalltalk podría muy bien tener un papel, incluso en ese mundo
de traje y corbata. Un programador de Smalltalk podría
desarrollar clases que encapsulen el conocimiento necesario
para extraer datos del entorno, y estas clases se utilizarían
para permitir que otros programadores menos experimentados
atendiesen directamente al ejecutivo.
54. Está claro que Smalltalk es la solución, pero, ¿cuál es el problema?
Smalltalk podría muy bien tener un papel, incluso en ese mundo
de traje y corbata. Un programador de Smalltalk podría
desarrollar clases que encapsulen el conocimiento necesario
para extraer datos del entorno, y estas clases se utilizarían
para permitir que otros programadores menos experimentados
atendiesen directamente al ejecutivo. El entorno de la
computadora personal podría funcionar como acoplamiento de
impedancias entre las necesidades del ejecutivo y los límites
de la computación organizada.
56. Ada
La publicidad que rodea a este lenguaje es tan amplia que
apenas es necesario mencionarlo de nuevo. Realizado por el
Ministerio de Defensa de los Estados Unidos, Ada fue diseñado
como sustituto de tecnología punta para la variada colección
de lenguajes que se utilizaban para construir sistemas
empotrados de computadoras. A lo largo de todo el proyecto se
tuvo la intención explícita de que Ada fuese obligatorio para
trabajar con sistemas empotrados, en los cuales la computadora
es un componente relativamente pequeño que forma parte de un
sistema mucho más grande, y que implica superficies de control
de aeronaves, sistemas de armamento, ayudas para la
navegación, sistemas de comunicaciones y cosas parecidas.
57. Ada
El aspecto exacto en que los
sistemas empotrados se
diferencían de los normales, no
ha estado nunca claro. Es
probable que esta ambigüedad sea
intencionada, porque el
objetivo, desde el principio, ha
sido el de reducir el número de
dialectos de lenguajes.
Ada siempre ha estado rodeado de
controversias. Sus diseñadores
han sido acusados de padecer del
síndrome del cajón de sastre,
porque Ada es un lenguaje
amplio, lleno de posibilidades,
y extremadamente complicado.
58. Ada
Hay características complejas y posiblemente mal comprendidas,
como la multitarea y la gestión de excepciones, que se definen
como parte del lenguaje; es probable que estas capacidades
debieran haber sido omitidas en el lenguaje, ofreciéndose en
apéndices separables como bibliotecas de subrutinas o paquetes
de Ada. Los argumentos de ambos lados son comprensibles, dado
el énfasis del Departamento de defensa para evitar una
proloferación de dialectos posiblemente incompatibles.
59. Características orientadas a objetos de Ada
De cualquier forma, aquí no vamos a hablar de Ada como
lenguaje, sino del sentido en que se dice que Ada, y otros
lenguajes como Ada, admiten una programación orientada a
objetos.
Hasta ahora debería ser claro que el objetivo de Ada no es
acrecentar el reino de las cosas que se pueden hacer con las
computadoras, sino el de ofrecer una sola forma de hacer las
cosas que hacen muchos lenguajes incompatibles pero parecidos.
60. Características orientadas a objetos de Ada
La complejidad de las capacidades de Ada suele obscurecer el
hecho de que Ada es, básicamente, un lenguaje convencional.
Ada no tiene nada que pueda sorprender a un usuario de C,
Pascal o FORTRAN que esté acostumbrado a la multitarea y a la
gestión de excepciones que se han pegado al lenguaje base
mediante bibliotecas de subrutinas.
Ada es un lenguaje con comprobación estricta de tipos que
lleva a cabo todo el enlazado en el momento de la compilación.
Los tipos de todos los datos se declaran explícitamente; es el
compilador el que toma todas las decisiones en el momento de
la compilación, y no los objetos durante la ejecución.
61. Características orientadas a objetos de Ada
Según las definiciones de Smalltalk, un objeto son unos datos
privados más el grupo de procedimientos que pueden acceder a
esos datos. Esta encapsulación de datos y procedimientos se
logra haciendo que los mensajes sean la única forma en que se
puede acceder a cualquier objeto. Dado que la ligadura se
retrasa hasta el momento en que se envía el mensaje, no hay
dificultad para trabajar con colecciones débilmente acopladas
que contengan objetos de distintos tipos.
Procedimiento Procedimiento Procedimiento
objeto
Datos privados
62. Características orientadas a objetos de Ada
Según las definiciones de Smalltalk, un objeto son unos datos
privados más el grupo de procedimientos que pueden acceder a
esos datos. Esta encapsulación de datos y procedimientos se
logra haciendo que los mensajes sean la única forma en que se
puede acceder a cualquier objeto. Dado que la ligadura se
retrasa hasta el momento en que se envía el mensaje, no hay
dificultad para trabajar con colecciones débilmente acopladas
que contengan objetos de distintos tipos.
Procedimiento Procedimiento Procedimiento
Datos privados
63. Características orientadas a objetos de Ada
Según las definiciones de Smalltalk, un objeto son unos datos
privados más el grupo de procedimientos que pueden acceder a
esos datos. Esta encapsulación de datos y procedimientos se
logra haciendo que los mensajes sean la única forma en que se
puede acceder a cualquier objeto. Dado que la ligadura se
retrasa hasta el momento en que se envía el mensaje, no hay
dificultad para trabajar con colecciones débilmente acopladas
que contengan objetos de distintos tipos.
Mensaje
Procedimiento Procedimiento Procedimiento
Datos privados
64. Características orientadas a objetos de Ada
En Ada, el mecanismo de encapsulación lo proporciona en su
totalidad el compilador, y ha desaparecido antes de la
ejecución. Esta es la ventaja de Ada, y también su
inconveniente. Es una ventaja para el propósito para el que se
diseñó Ada: eliminar la necesidad de múltiples lenguajes
convencionales para construir aplicaciones convencionales.
Es mejor para construir colecciones fuertemente acopladas en
las cuales el tipo de cada componente pueda ser conocido y
especificado por adelantado, porque el compilador puede
comprobar que cada uno de los componentes sea el tipo
especificado.
65. Características orientadas a objetos de Ada
Es un inconveniente en problemas en que el cambio no se pueda
gestionar editando el fuente y el recompilando. El factor
clave para la distinción es el grado hasta el cual se puede
tratar el cambio al principio de diseño, antes de que el
programa llegue al compilador.
En Ada, el proveedor de una nueva capacidad la ofrece
definiendo un paquete. El paquete contiene algunas partes que
serán propiedad privada del proveedor, y otras que deben ser
publicadas para el código del consumidor. Típicamente, el
código y la distribución precisa de los campos dentro del
objeto son privados, pero esto no es necesario en modo alguno.
El proveedor decide lo que ha de publicarse, y lo que no.
66. Paquetes
Por ejemplo, el proveedor de un paquete de gráficos podría
definir un nuevo tipo de datos, vector, para manejar
coordenadas bidimencionales.
package PaqueteGeometriaBiDimensional is
type vector is record
x : integer;
y : integer;
end record
function “+” (a,b: in vector) return vector;
function “-” (a,b: in vector) return vector;
end PaqueteGeometriaBiDimensional;
67. Paquetes
Este paquete define una interfaz entre el consumidor y el
proveedor pero no la realización que subyace a esta interfaz.
Esto se describe por separado, en el cuerpo del paquete:
package body PaqueteGeometriaBiDimensional is
function “+” (a,b : in vector) return vector
is
begin
-- instrucciones
end
function “-” (a,b : in vector)
begin
-- instrucciones
end
begin
-- instrucciones para la iniciación
end PaqueteGeometriaBiDimensional
68. Paquetes
El consumidor indica al compilador que utilice un paquete
mediante una sentencia with, dando lugar a que las partes
públicas del paquete sean conocidas para el código del
consumidor. El consumidor puede utilizar los servicios del
paquete en cualquier forma que haya previsto el proveedor. Por
ejemplo:
with PaqueteGeometriaBiDimensional;
origen, extension, esquina: vector;
esquina = origen + extension;
a + b a - b
Datos privados
PaqueteGeometriaBiDimensional
69. Paquetes
Obsérvese que Ada permite la sobrecarga de operadores, de tal
modo que los operadores de nombres convencionales, como +,
pueden recibir significados especiales para tipos de datos
definidos por el usuario. El compilador es capaz de apreciar
que:
esquina = origen + extension;
No debe tratarse de la misma forma que:
suma = 2 + 2
Porque el compilador sabe que origen y extension son del tipo
vector, y que un paquete ha invalidado el significado
convencional del símbolo + para este tipo. Aunque las ventajas
de la sobrecarga de operadores son evidentes para los símbolos
matemáticos convencionales como +, también es aplicable a
nombres de funciones convencionales, como sqrt,
calcCorreccionGisroscopio, o aceleraAMaximoImpulso
70. Discusión
La aproximación de Ada a la programación orientada a objetos,
tiene sus ventajas y sus inconvenientes, y no es correcto
afirmar con ademán categórico y aire ofendido que “Esto es una
ventaja” o que “Eso es un inconveniente”, sin dejar claro
“¿con respecto a qué alternativa?” o bien ¿Es el contexto de
qué problema?”
Una de las decisiones claves de Ada es que la semántica de un
programa dado debería quedar determinada estáticamente. Ada
lleva la ligadura estática más allá que los lenguajes de
programación anteriores, como C. Pero para aquellos programas
que no puedan ser especificados estáticamente, Ada sólo ofrece
tipos de acceso. Los tipos de acceso son únicamente punteros;
son trucos que permiten al programador realizar colecciones
débilmente acopladas de la misma manera que se haría en C,
realizando manualmente la ligadura dinámica con ligadura por
parte del consumidor.
71. Discusión
Una de las causas de desilución de Ada son las limitaciones a
la hora de definir tipos nuevos reutilizando algún tipo
existente. Aunque Ada proporciona tipos y subtipos derivados,
esto no es sino una forma de restringir tipos generales, como
el integer, para limitarlos a un cierto intervalo o propósito
específico, como diaDeLaSemana. Ninguno de ellos posibilita la
extensión de un tipo preexistente añadiendo cambios y
operaciones adicionales.
Esto es un problema serio, porque elimina la posibilidad,
incluso, de tener tipos de herencia limitados, y obliga al
desarrollador de cada tipo nuevo a duplicar un código que está
contenido en tipos más generales.
72. Discusión
El concepto de paquete (package) es una verdadera mejora con
respecto a los lenguajes convencionales como C. Pero su
importancia es difícil de cuantificar. Su mejora es comparable
a la mejora consistente en pasar de un lenguaje no
estructurado como FORTRAN a un lenguaje estructurdo como C,
pero de importancia menor que la obtenida al pasar del
lenguaje ensamblador a FORTRAN. Otras partes de la filosofía
de Ada, sobre todo la insistencia en que haya un único
lenguaje para todos los desarrollos de software, tienen mayor
probabilidad de proporcionar ventajas realmente
significativas.
73. Discusión
La ligadura estática obtiene su eficiencia acoplando las
decisiones realizadas por el proveedor con las del consumidor
en el momento de la compilación, exactamente igual que sucede
en los lenguajes convencionales que el DOD había estado
utilizando por décadas. Ada ofrece posibilidades nuevas para
hacer disminuir este acoplamiento, pero, ciertamente ofrece un
excelente apoyo para gestionar el acoplamiento fuerte de una
manera cómoda. Y quizás esto sea para bien, porque Ada ya es
demasiado grande y demasiadocomplicado para su propio bien.
¿por qué vamos a lamentar el hecho de que sólo admita la
ligadura estática, cuando se puede añadir la ligadura
dinámica?
74. C++
C++ es una mejora evolutiva del lenguaje C desarrollado en
Bell Laboratories. C++ es particularmente interesante en vista
del énfasis que haremos en C objetivo, porque hace contrastar
lo que se puede lograr redefiniendo el lenguaje de
programación en sí, frente a lo que se consigue añadiendo
capacidades orientadas a objetos a un lenguaje base inmutable.
C-Objetivo añade objetos ligados dinámicamente, clases y
herencia al lenguaje C estándar. Esto añade justamente las
capacidades sificientes para admitir la encapsulación y la
herencia, lo suficiente para que se pueda aplicar la
tecnología de software integrado a problemas de construcción
de sistemas y nopara mejorar el lenguaje de programación en
sí.
75. Laboratorios Bell
C++ fue evolucionando en los Laboratorios Bell para alcanzar
los objetivos siguientes:
1.- Mantener la extremadamente alta eficiencia y
transportabilidad por las cuales es famoso C
2.- Mantener la compatibilidad entre C++ y C
3.- Corregir algunos fallos de largo tiempo soportados,
concretamente la lasitud de C a efectos del tratamiento de
tipos. C ha sido criticado desde hace mucho tiempo por su
débil comprobación de tipos, incluso dentro de una función
dada, y por no hacer comprobación de tipos entre funciones, ni
siquiera dentro del mismo archivo.
4.- Actualizar a C para adecuarlo a los modernos principios de
ocultación de información.
76. Laboratorios Bell
C++ es casi un superconjunto puro del lenguaje C, con unas
pocas incompatibilidades de escasa importancia. Entre sus
mejoras se cuenta la posibilidad de definir nuevos tipos de
datos (clases), operaciones con esos tipos (operadores y
funciones), y un amplio conjunto de maneras de controlar las
operaciones que se hagan con esos tipos, entre las que se
incluye la sobrecarga de operadores, los constructores y los
destructores.
77. Clases
Los nuevos tipos de datos se definen mediante la sentencia
class, que es una generalización de la vieja sentencia struct,
a la cual sustituye, pero que se mantiene a efectos de
compatibilidad hacia atrás (struct se trata como un caso
especial de class, en el cual todos los miembros son
públicos). Por ejemplo, lo que sigue es equivalente a la
declaración de una struct:
class ostream {
public:
FILE *file;
int nextchar;
char buff[128];
};
78. Clases
Los nuevos tipos de datos se definen mediante la sentencia class, que es
una generalización de la vieja sentencia struct, a la cual sustituye, pero
que se mantiene a efectos de compatibilidad hacia atrás (struct se trata
como un caso especial de class, en el cual todos los miembros son
públicos). Por ejemplo, lo que sigue es equivalente a la declaración de una
struct:
class ostream {
public:
FILE *file;
int nextchar;
char buff[128];
};
Así se declara una clase nueva, ostream, con tres miembros: file, nextchar
y buf. La palabra reservada public: hace que estos nombres sean públicos, y
que pueda acceder a ellos cualquier programa que contenga esta declaración.
La única diferencia entre una class y una struct es que los miembros de la
struct son públicos por omisión, mientras que los miembros de la class son
privados (private) a no ser que se indique explícitamente lo contrario.
Aunque las structs solo podían tener a datos como miembros, las clases
también pueden tener miembros de procedimientos, o funciones. Estas
funciones pueden ser de dos tipos: funciones friend y funciones member.
79. Funciones friend
Las funciones friend son funciones convencionales de C. No tienen relación
especial con la clase, salvo que se les permite hacer referencia a
cualquier miembro que sea un dato y haya sido declarado private (por
aparecer delante del marcador public:)
class fecha {
int dia, mes, agno;
public:
friend void fijaFecha(fecha*, int, int, int);
friend void siguienteFecha(fecha*);
friend void siguienteHoy();
friend void imprimirFecha(fecha*);
}
80. Funciones friend
Las funciones friend son funciones convencionales de C. No tienen relación
especial con la clase, salvo que se les permite hacer referencia a
cualquier miembro que sea un dato y haya sido declarado private (por
aparecer delante del marcador public:)
class fecha { Esto hace que la realización
int dia, mes, agno; de las fechas sea privada
public: (private), y que sólo se
friend void fijaFecha(fecha*, int, int, int); pueda acceder a ellas
friend void siguienteFecha(fecha*); mediante las cuatro funciones
friend void siguienteHoy(); friend.
friend void imprimirFecha(fecha*);
}
81. Funciones friend
Las funciones friend son funciones convencionales de C. No tienen relación
especial con la clase, salvo que se les permite hacer referencia a
cualquier miembro que sea un dato y haya sido declarado private (por
aparecer delante del marcador public:)
class fecha { Esto hace que la realización
int dia, mes, agno; de las fechas sea privada
public: (private), y que sólo se
friend void fijaFecha(fecha*, int, int, int); pueda acceder a ellas
friend void siguienteFecha(fecha*); mediante las cuatro funciones
friend void siguienteHoy(); friend.
friend void imprimirFecha(fecha*);
}
Los tipos de los argumentos que admiten estas funciones también se
declaran; estos tipos no sólo son comprobados por el compilador,
sino que, además, se utilizan también para guiar las decisiones de
enlazado.
82. Funciones friend
Las funciones friend son funciones convencionales de C. No tienen relación
especial con la clase, salvo que se les permite hacer referencia a
cualquier miembro que sea un dato y haya sido declarado private (por
aparecer delante del marcador public:)
class fecha { Esto hace que la realización
int dia, mes, agno; de las fechas sea privada
public: (private), y que sólo se
friend void fijaFecha(fecha*, int, int, int); pueda acceder a ellas
friend void siguienteFecha(fecha*); mediante las cuatro funciones
friend void siguienteHoy(); friend.
friend void imprimirFecha(fecha*);
}
Los tipos de los argumentos que admiten estas funciones también se
declaran; estos tipos no sólo son comprobados por el compilador,
sino que, además, se utilizan también para guiar las decisiones de
enlazado.
Esta clase podría utilizarse, por tanto, como sigue:
fecha miCumpleagnos, hoy;
fijarFecha(&miCumpleagnos,30,12,1980);
fijarFecha(&hoy,12,11,2004);
imprimirFecha(&hoy);
siguienteFecha(&hoy);
83. Funciones miembro
Aunque las funciones friend son funciones convencionales, las
funciones miembro, sin embargo, están asociadas a la clase en
el mismo sentido en lo que lo están los miembros que son
datos. Las funciones miembro son las que dan a C++ su aroma
orientado a objetos. Sirven para realizar operaciones en una
instancia de alguna clase, mientras que las funciones friend
no son más que funciones estándar de C a las que se les
permite hacer referencia a los nombres de los miembros
privados. Las funciones miembro se declaran mencionando su
declaración dentro de la declaración de la clase, junto con la
declaración de las variables miembro:
class fecha {
int dia, mes, agno; /* la realizacion de las fechas*/
public:
void fijar(int int, int, int) /* la interfaz de las fechas*/
void siguiente();
void imprimir();
};
84. Funciones miembro
Las funciones miembro se invocan mediante una sintaxis que
refleja su papel de operaciones realizadas por un cierto
objeto, y sigue la pauta de la forma en que se accede a los
miembros de una estructura:
miCumpleagnos.imprimir();
hoy.siguiente();
Para definir una función miembro, es preciso proporcionar
también el nombre de su clase:
void fecha.siguiente(){
dia=dia + 1;
if(mes== FEB && dia > 28)
...
}
Tales funciones reciben siempre un argumento implícito, this,
que identifica al objeto que lleva a cabo la acción. En este
ejemplo, el campo dia se piede identificar tanto en la forma
dia como en la forma this->dia.
85. Clases derivadas
C++ también proporciona la posibilidad de definir subclases
con herencia, describiendo la forma en que la clase nueva
(derivada) difiere de alguna superclase anterior (a la que
hereda). Esta técnica es distinta en ciertos detalles de la
empleada por Objective-C, y pierde generalidad y espacio en
memoria para ganar una mayor comprobación de tipos en el
momento de la compilación y una cierta cantidad de eficiencia.
Por ejemplo, una clase de formas se podría definir como sigue:
class forma{
vector centro;
int color;
int color;
forma *siguiente;
public:
void mover(vector); /* cambiar la posicion de una forma */
vector donde(); /* responde con la posicion de la forma*/
virtual void rotar(int); /* rotar una forma */
virtual void dibujar(); /* mostrar una forma */
}
86. Clases derivadas
Las funciones virtuales son funciones que no se podrían
realizar sin conocer la forma concreta de que se trate, y que
deben ser invalidadas, por tanto en cada subclase:
class circulo{
float radio;
public:
void rotar(int){ ; } /* como se rota un circulo */
void dibujar(); /* como se dibuja un circulo */
...
};
La palabra reservada virtual indica que éstas funciones deben
enlazarse dinámicamente, y fuerza al compilador a añadir un
miembro invisible a cada instancia que indica explícitamente
su clase en el momento de la ejecución.
87. Clases derivadas
Ahora es posible definir subclases que obedezcan a un
protocolo común, de tal modo que se puede dbujar cualquier
forma mediante:
cualquierInstancia.dibujar();
C++ permite derivar una clase nueva a partir de múltiples
superclases (herencia múltiple). Los conflictos que surgen
como consecuencia de que la clase nueva herede miembros con
los mismos nombres de más de una clase se resuelven según un
cierto conjunto de reglas del lenguaje.
88. Clases derivadas
Por ejemplo, para derivar una clase llamada plato a partir de
las clases círculo y recipiente, que ya existían con
anterioridad, se crearía la declaración siguiente:
class plato: public circulo, recipiente { /* ... */ };
89. Clases derivadas
Además de mostrar que plato debe realizarse copiando las
variables y métodos de círculo y recipiente, esta sentencia
indica también el tipo de acceso a los miembros de las clases
base circulo y recipiente que tendrá un usuario de plato. La
palabra reservada public que va delante de circulo indica que
los usuarios de plato comparten los mismos privilegios de
acceso a los miembros protegidos y públicos de circulo que
posee el propio plato.
Por otra parte, la ausencia de una palabra reservada delante
de recipiente lo identifica como privado. El acceso a los
miembros públicos y protegidos de circulo está limitado
únicamente a plato; los usuarios de plato no pueden acceder en
absoluto a los miembros de recipiente. Este mecanismo permite
al diseñador de clases restringir de manera selectiva el
acceso a sus superclases.
90. Datos protegidos
Cuando se deriva una clase nueva de una clase vieja, surge la
duda: ¿a qué debería tener acceso la clase derivada? en C++ el
acceso de la clase derivada a los miembros de la clase base es
gestionado por el creador de la clase base. El creador puede
especificar que los miembros de la clase sean de acceso
público, privado o protegido. Supongamos que variamos la
definición de la clase forma para que quede como sigue:
class forma{ Las funciones miembro y las funciones
private:
forma *siguiente;
friend de las clases derivadas podrían
protected: acceder a los miembros “centro” y
vector centro; “color” de la clase forma, puesto que se
int color;
ha indicado que son protected. Sin
public:
.... embargo, no podrían acceder al miembro
} “siguiente”, puesto que ha sido marcado
como private
91. Sobrecarga de operadores
LAs capacidades descritas para las funciones son aplicables
también a otros operadores. Anteponiendo al símbolo de un
operador la palabra reservada operator, es posible ofrecer una
nueva realización de ese operador. Por ejemplo, el último par
de declaraciones que se ven a continuación definen la forma en
que debe comportarse “+” para la clase vectores:
class vector{
int x,y;
public
vector(int xc, int yc){x= xc; y= yc;} /* constructor */
vector(int xc){ x= xc; y=0; } /* constructor */
vector(vector p){ x= p.x; y=p.y;} /* constructor */
friend vector operator+(vector, vector); /* sumar dos vectores */
friend vector operator+(vector, int); /* sumar un vector y un entero */
...
}
92. Sobrecarga de operadores
Las capacidades descritas para las funciones son aplicables
también a otros operadores. Anteponiendo al símbolo de un
operador la palabra reservada operator, es posible ofrecer una
nueva realización de ese operador. Por ejemplo, el último par
de declaraciones que se ven a continuación definen la forma en
que debe comportarse “+” para la clase vectores:
class vector{
int x,y;
public
vector(int xc, int yc){x= xc; y= yc;} /* constructor */
vector(int xc){ x= xc; y=0; } /* constructor */
vector(vector p){ x= p.x; y=p.y;} /* constructor */
friend vector operator+(vector, vector); /* sumar dos vectores */
friend vector operator+(vector, int); /* sumar un vector y un entero */
...
}
93. Sobrecarga de operadores
Esto define vectores en unplano bidimensional de coordenadas
enteras. Las tres funciones llamadas vector son constructores.
Los constructores definen la forma en que se construyen los
nuevos vectores cuando aparecen en sentencias de iniciación y
también cuando se construyen muevos vectores en la pila al
llamar a una función.
Dado que la declaración también contiene la realización de
estos operadores, la realización se expandirá en línea, y no
se incurrirá en un gasto adicional de tiempo para dar valores
iniciales a los vectores. Esa característica de expansión en
línea se aplica a cualquier tipo de operador que pueda ser
declarado en una clase, no sólo en los constructores
94. Sobrecarga de operadores
Los tres operadores restantes definen la forma en que funciona
el operador + cuando los dos lados son vectores, o cuando el
lado derecho es un entero. La declaración podría extenderse,
para construir una clase de vectores completa, con productos
por escalares, productos vectoriales, productos tensoriales,
etc.
vector este = (1), norte = (0, 1);
vector norEste = norte + este;
95. Administración de la memoria
En C++ es posible asignar dinámicamente nuevos objetos en el
montículo (heap), y después se accede a ellos mediante sus
direcciones. También se pueden reservar objetos estáticamente,
y se accede a ellos por su nombre, como en el caso de los tres
vectores que se han mostrado en el ejemplo anterior. En el
momento de la ejecución, el espacio correspondiente a los
objetos conocidos por sus nombres debe recibir valores
iniciales siempre que su nombre quede dentro del ámbito. Por
ejemplo:
96. Administración de la memoria
1.- Los objetos que se pasen como argumentos a funciones, y
los objetos que se declares como variables locales (auto),
deben recibir valores iniciales cuando se llamen a esa
función.
2.- Los objetos que porporcionan las funciones deben recibir
valores iniciales cuando retorne la función.
3.- Los objetos que estén en la pila de llamada a la función
(los argumentos y variables locales) deben ser destruidos
cuando la función retorne y se retraiga la pila.
97. Administración de la memoria
C++ ofrece un camino para que el desarrollador de la clase
especifique lo que debería suceder en estos casos. El ejemplo
del vector muestra cómo se especifican los operadores de
construcción. La inversa es una operación destructor, cuyo
nombre será el nombre de la clase precedido por el símbolo
“~”. Por ejemplo, una clase de cadenas podría ser:
class cadena {
int longitud;
char *bytes;
cadena(char *); /*constructor de cadenas */
~cadena(){ delete bytes }; /* destructor de cadenas */
public:
int longitud(){ return longitud }
char *texto(){ return bytes }
};
cadena.cadena(char *c){
longitud=strlen(c);
bytes = new char[longitud +1];
strcpy(bytes, c);
}
98. Administración de la memoria
Esto garantiza que todas las instancias de cadenas que se
creen cuando las cadenas se pasen a funciones, y cuando éstas
las proporcionen, sean una sola copia. Pero no se gestionan
las referencias múltiples que se crean cuando se asigna
explícitamente una cadena a otra en una sentencia de
asignación. Esto se puede lograr invalidando el operador de
asignación.
99. Administración de la memoria
Obsérvese que, aun cuando esto no sustituye a la recolección
automática de basura, puede, a veces, disminuir la necesidad
de llevarla a cabo. La recolección automática de basura sigue
siendo deseable cuando se hacen múltiples referencias a los
objetos a través de punteros. Copiando los objetos cada vez
que se necesitan, no existen las referencias múltiples, a sí
que es posible liberar los objetos siempre que quedan fuera de
nuestro ámbito. Por ejemplo, la realización de cadenas que se
muestra aquí implica la reserva e iniciación de una copia cada
vez que se pasa la cadena a una función, y el tiempo adicional
requerido podría fácilmente resultar inadmisible. C++ no
ofrece recolección automática de basura.
100. Compilación por separado
Cada compilación se realiza de modo aislado, C++ no recuerda
las compilaciones anteriores, así que todas las declaraciones
acerca de clases externas deben ser incorporadas manualmente a
cada archivo fuente. C++ no ofrece más ayuda para hacer esto
que la habitual sentencia #include. No impone restricciones a
la forma en que se haga esto, ni realiza ninguna comprobación
para asegurarse de que la información sea congruente entre
compilaciones.
101. Compilación por separado
En la práctica, para cada clase se preparan dos archivos. El
primero es un archivo de declaraciones, que debe ser incluído
en todos los archivos que utilicen esa clase. El segundo es un
archivo de definiciones, que se compila y se archiva, y que el
enlazador combina para formar la imagen ejecutable. Todo el
contenido del primer archivo es, por tanto, información
pública, mientras que el segundo es verdaderamente privado
sólo cuando se compila en forma binaria. Esto hace que las
distinciones entre público y privado que ofrece la declaración
de las clases induzcan a la confusión. El archivo se puede
leer desde fuera del lenguaje; se puede, incluso, copiar y
modificar para hacer que el código de un consumidor pueda
acceder a la información privada.
102. ¿Qué significa “orientado a objetos”?
Hemos empezado este capítulo preguntándonos ¿Qué significa
orientado a objetos? Incluso después de estudiar varios
lenguajes diferentes que son orientados a objetos, queda
todavía una incertidumbre considerable acerca de lo que
significa este calificativo.
Nadie se siente confuso cuando se emplean adjetivos como
“pequeño” o “rápido”. Pero con respecto al desarrollo de SW es
muy fácil perder la orientación. Por tanto para entender el
significado de cualquier calificativo, y especialmente
“orientado a objetos”, debemos poner especialmente cuidado
para especificar el contexto en que se aplica.
103. ¿Qué significa “orientado a objetos”?
Hemos empezado este capítulo preguntándonos ¿Qué significa
orientado a objetos? Incluso después de estudiar varios
lenguajes diferentes que son orientados a objetos, queda
todavía una incertidumbre considerable acerca de lo que
significa este calificativo.
Nadie se siente confuso cuando se emplean adjetivos como
“pequeño” o “rápido”. Pero con respecto al desarrollo de SW es
muy fácil perder la orientación. Por tanto para entender el
significado de cualquier calificativo, y especialmente
“orientado a objetos”, debemos poner especialmente cuidado
para especificar el contexto en que se aplica.