1 de 14
Práctica
1.
Se propone terminar la arquitectura (diagrama de clases) del problema propuesto en
el primer ejemplo, para completar la implementación.
Semana 2
Semana 3
Semana 4
Ejemplo
5.
Este ejemplo muestra la relación entre una interfaz, una clase adaptadora
(abstracta) y dos implementaciones concretas.
Principios teóricos estudiados:
• Principio de Responsabilidad Única
• Patrón de delegación (Delegate)
Práctica
2.
Se plantea un problema de mediana complejidad donde se utilicen las clases
implementadas en los ejemplos anteriores. Se debe crear una nueva clase (cliente) que
es una especialización de la clase persona, agregando un nuevo atributo (id) y una
asociación con la clase cuenta del ejemplo 4. Se crea una clase para encapsular el manejo
de los clientes en la aplicación, proveyendo métodos que serán llamados directamente
desde una clase de frontera (interfaz). Se menciona cómo el término interfaz es utilizado
con diferente significado en diferentes contextos: como el conjunto de métodos públicos
de una clase, como la declaración de un conjunto de métodos públicos que deben
implementarse en una clase derivada, como un estereotipo de clase (donde la clase sirve
de frontera entre la aplicación y el usuario u otros sistemas) y como una clase específica
para manejar las entradas del usuario y el despliegue de resultados.
Semana 5
Práctica
3.
Sirve de ejemplo para el manejo de la interfaz de usuario desde la consola (para que
los estudiantes completen la práctica anterior). Se define una clase de control que maneja
las opciones del usuario solicitadas a través de la interfaz. El ejemplo sirve para también
presentar el concepto de arquitectura de software y el modelo MVC.
Ejemplo
6.
Es un ejemplo simple para mostrar los problemas asociados a la técnica de
encadenamiento de métodos: transitividad de las dependencias (Ley de Deméter o
del Conocimiento Mínimo) y exposición de la implementación. Los problemas se
resuelven fácilmente por delegación.
(Nota: se debería verificar el caso de la dependencia transitiva que no es visible en un
diagrama de clase)
Semana 6
Ejemplo
7.
Se utilizan las clases de la práctica 3 para mostrar cómo hacer una generalización de
la clase arreglo a un contenedor. Luego se muestra la implementación de una clase
concreta que implementa la interfaz del contenedor (lista), y se sustituye en la clase
conjuntoPersonas. Así se muestra como se puede sustituir una implementación por
otra si las dependencias son hacia interfaces o clases abstractas, en lugar de clases
concretas.
Ejemplo
8.
Este ejemplo se utiliza para estudiar la implementación de la clase lista. Se agrega
un apuntador al final de la lista para facilitar el agregar elementos al final de la lista. Se
agregan métodos generales que pueden utilizarse para el manejo de colecciones, que
serán generalizados luego a la interfaz del contenedor e implementados también en el
arreglo.
Se sugiere que la lista podría utilizarse para implementar pilas y colas utilizando
delegación.
Se escribe un método para eliminar todos los elementos de la lista considerando una
implementación por agregación o por composición, purgando la memoria asignada a cada
elemento individual de la colección.
La implementación de los métodos que permiten insertar y eliminar un elemento en
una posición arbitraria se dejan como tarea, implementando solamente stubs de dichos
métodos.
Semana 8
Experimento
1.
Este ejemplo es para mostrar qué problemas pueden presentarse si se llama a un
método virtual en un constructor o en un destructor. En general, el polimorfismo NO
funciona en un constructor o un destructor, aunque trabaje correctamente en otro
contexto.
Ejemplo
10.
Este ejemplo introduce el concepto del patrón Iterador, como una solución
generalizada (a través de una clase). La idea principal a mostrar es cómo el recorrido de
un contenedor puede implementarse utilizando una clase con métodos generales
(masElementos() y proximoElemento()) sin tener que exponer la implementación. En
el caso de la lista, se puede proveer la funcionalidad sin que el cliente de la clase requiera
conocer la clase Nodo, por ejemplo.
Práctica
4.
Se propone construir un programa para modelar la siguiente situación: se tiene un
grupo de personas, cada una de las cuales tiene un nombre, dos apellidos y un género
(femenino o masculino). Las personas pueden tener un padre y una madre (de géneros
diferentes), que son a su vez personas. Además, cada persona puede tener un conjunto
(lista) de hijos de tamaño indeterminado.
Ejemplo
11.
Solamente se hacen varias declaraciones para verificar la sintaxis.
Ejemplo
12.
Muestra el funcionamiento del constructor de copia. El ejemplo muestra uno de los
problemas que existen al utilizar instancias de una clase en lugar de apuntadores
(referencias). Cuando se utiliza una instancia como argumento de una función, esto
fuerza la creación de una copia del objeto (parámetro por valor). Es preferible utilizar
un parámetro por referencia.
Ejemplo
14.
Muestra la forma de implementar una matriz (arreglo de dos dimensiones) de
apuntadores a objetos. Este ejemplo sirve de apoyo para la implementación del proyecto
asignado (juego de ajedrez).
Experimento
2
Muestra el uso de una declaración por referencia, para poder tener dos variables
asociadas a la misma dirección de memoria. Es una característica de bajo nivel, propia de
C++.
Experimento
3
Se utiliza el ejemplo (asociado al proyecto asignado) para mostrar cómo manejar el
caso de dos clases que dependen mutuamente.
Cuando ocurre una situación similar, una de las dos instancias debe crearse primero,
y luego se establecerá la dependencia al crear la segunda instancia. Generalmente la
primera instancia crea la segunda (lo que establece una relación de composición), la cual
recibe como argumento en el constructor la referencia del objeto principal por medio de
un apuntador this. (Ver el ejemplo 16)
Ejemplo
16.
Muestra cómo se implementa la dependencia mutua entre dos clases.
Ejemplo
17.
Muestra la definición de dos clases en una jerarquía simple para ilustrar la diferencia
entre los conceptos de upcasting y downcasting. Se menciona el hecho de que el
upcasting es siempre seguro e implícito, pero asume que una subclase es un subtipo (lo
cual no es cierto siempre). El término casting (coerción) se refiere usualmente al concepto
de downcasting, que debe ser explícito. A menudo es inseguro, si no se puede determinar
el tipo dinámico de una variable.
Cuando una clase es parte de una relación de agregación como componente, puede formar
parte de otra relación de agregación, pero no el caso de la composición. Los
componentes (partes) en una relación de composición no pueden ser
compartidos. Las relaciones de agregación y composición modelan una relación “tiene
un” entre el objeto agregado (compuesto) y sus elementos componentes.
Esto implica también que la relación de composición solamente puede tener una
multiplicidad de 1 en el extremo del objeto compuesto, ya que un objeto componente
solamente puede serlo de un único compuesto, aunque también podría formar parte de
varios agregados.
Al copiar un objeto agregado, los componentes no se copian, en general.
Suponga, por ejemplo, que se tienen dos clases en una relación de agregación como se
muestra:
Por ejemplo, suponga que existe si se copia el objeto obj1 de la clase c1, la copia
mantiene la referencia al mismo atributo asociado de tipo a1
Sin embargo si la relación entre las clases es una de composición, el atributo asociado no
puede compartirse entre las dos instancias de la clase c1 (la original y la copia). Por lo
tanto, es necesario hacer una copia del atributo:
1 http://ootips.org/uml-hasa.html
http://www.c-sharpcorner.com/UploadFile/pcurnow/compagg07272007062838AM/compagg.aspx
http://wiki.answers.com/Q/Whats_the_difference_between_aggregation_and_composition
http://stackoverflow.com/questions/885937/difference-between-association-aggregation-and-composition
2 Es importante notar que por restricciones de la implementación, algunas veces debe crearse primero el
objeto compuesto y luego los componentes. Sin embargo, al destruir el objeto compuesto, los componentes
se destruyen primero, por lo que el tiempo de vida de los componentes no puede exceder en ningún caso
el del compuesto. Cuando se trata de un agregado, los objetos componentes pueden existir aunque se
haya eliminado el agregado, o éste haya salido de alcance. Algunas veces se usa como ejemplo de
agregación un objeto cuyas partes son “reutilizadas” en otro agregado (como en el ejemplo del avión que
es destruido y sus piezas son empleadas entonces para otro avión), pero éste es un ejemplo
INCORRECTO, ya que la relación es de composición estrictamente (las piezas no pueden serlo de dos
aviones de manera simultánea).
Semana 12
Ejemplo
18
Este ejemplo construye una clase que encapsula un arreglo (una versión más simple
que la utilizada en general) usando plantillas (templates). Se llama la atención sobre el
problema de incluir la implementación de los métodos en un archivo fuente (.cpp). En su
lugar, todos los métodos (las plantillas de los métodos) deben incluirse en los archivos de
cabecera (.h).
Se estudian los conceptos de:
• Polimorfismo estático (plantillas)
• Sobrecarga de operadores
Se plantea la modificación de las clases que implementan contendores (arreglos y
listas) para que utilicen polimorfismo estático (plantillas) en lugar de polimorfismo
dinámico (herencia).
Se enuncia un principio importante de POO: en general, deberá preferirse la
delegación al uso de polimorfismo, y deberá preferirse el polimorfismo estático
(programación genérica o plantillas) al polimorfismo dinámico (herencia).
Ejemplo
20
Ejemplo básico de uso de excepciones.
© 2010. Georges E. Alfaro S.
p. 14 de 14
Ejemplo
21
Ejemplo de uso de una clase de excepción y de anidamiento de bloques try – catch.
Ejemplo
22
Implementación de funciones de biblioteca para la conversión de texto a mayúsculas y
minúsculas (no es un ejemplo dentro de la secuencia del curso).
Ejemplo
23
Muestra de los mecanismos de indirección disponibles en C++ (no es un ejemplo
dentro de la secuencia del curso).
Semana 14.