# Utilizando objetos en C++ - Pájaros ![](images/headerBirds.png) [Verano 2016 - Ive - Tatiana] Hasta ahora hemos visto cómo utilizar variables para guardar y manipular datos de cierto tipo y cómo estructurar nuestros programas dividiendo las tareas en funciones. Un *objeto* es una entidad que se utiliza en muchos lenguajes de programación para integrar los datos y el código que opera en ellos, haciendo más fácil el modificar programas grandes. En la experiencia de laboratorio de hoy, utilizarás una clase llamada `Bird` para practicar algunas de las destrezas básicas en C++ para la creación y manejo de objetos. ## Objetivos: 1. Crear objetos de una clase. 2. Analizar la declaración de una clase para entender cómo crear y manipular objetos de esa clase. 3. Practicar la creación y manipulación de objetos, y la invocación de *"setters"* y *"getters"*. ## Pre-Lab: Antes de llegar al laboratorio debes haber: 1. Repasado los siguientes conceptos: a. La creación de objetos de una clase. b. La utilización de métodos *"getters"* para acceder a los atributos de un objeto. c. La utilización de métodos *"setters"* para modificar los atributos de un objeto. 2. Estudiado la documentación de la clase `Bird` disponible dentro de la documentación del proyecto (`objects-birds/doc/es/html/class_bird.html`). 3. Estudiado los conceptos e instrucciones para la sesión de laboratorio. 4. Tomado el quiz Pre-Lab, disponible en Moodle. --- --- ## Clases y objetos en C++ Un *objeto* es un ente que contiene datos y procedimientos para manipularlos. Al igual que cada variable tiene un *tipo* de dato asociada a ella, cada objeto tiene una *clase* asociada que describe las propiedades de los objetos: sus datos (*atributos*), y los procedimientos con los que se pueden manipular los datos (*métodos*). Para definir y utilizar un objeto no hay que saber todos los detalles de los métodos del objeto pero hay que saber cómo crearlo, y cómo interactuar con él. La información necesaria está disponible en la documentación de la clase. Antes de crear objetos de cualquier clase debemos familiarizarnos con su documentación. La documentación nos indica, entre otras cosas, que ente se está tratando de representar con la clase, y cuáles son los interfaces o métodos disponibles para manipular los objetos de la clase. Dale un vistazo a la documentación de la clase `Bird` que se encuentra en [este enlace] (http://ada.uprrp.edu/~ranazario/bird-html/class_bird.html). ### Clases Una clase es una descripción de los datos y procesos de un objeto. La declaración de una clase establece los atributos que tendrá cada objeto de esa clase y los métodos que pueden invocar. Si no se especifica lo contrario, los atributos y métodos definidos en una clase serán privados. Esto quiere decir que esas variables solo se pueden acceder y cambiar por los métodos de la clase (*constructores*, *"setters"* y *"getters"*, entre otros). Lo siguiente es el esqueleto de la declaración de una clase: --- ``` class NombreClase { // Declaraciones private: // Declaraciones de variables o atributos y // prototipos de métodos // que sean privados para esta clase tipo varPrivada; tipo nombreMetodoPrivado(tipo de los parámetros); public: // Declaraciones de atributos y // prototipos de métodos // que sean públicos para todo el programa tipo varPública; tipo nombreMetodoPúblico(tipo de los parámetros); }; ``` --- Puedes ver la declaración de la clase `Bird` en el archivo `bird.h` incluido en el programa de esta experiencia de laboratorio. ### Objetos Un objeto es un ente que contiene datos (al igual que una variable), llamados sus `atributos`, y también contiene procedimientos, llamados `métodos`, que se usan para manipularlos. Los objetos son *instancias* de una clase que se crean de manera similar a como se definen las variables: `NombreClase nombreObjeto;` Una vez creamos un objeto, podemos interactuar con él usando los métodos de la clase a la que pertenece. ### Métodos de una clase Los métodos de una clase determinan qué acciones podemos tomar sobre los objetos de esa clase. Los métodos son parecidos a las funciones en el sentido de que pueden recibir parámetros y regresar un resultado. Una forma elemental de conocer los métodos de una clase es leyendo la declaración de la clase. Por ejemplo, el siguiente código es parte de la declaración de la clase `Bird` en el archivo `bird.h`. --- ``` class Bird : public QWidget { . . . Bird(int , EyeBrowType , QString , QString, QWidget *parent = 0) ; int getSize() const; EyeBrowType getEyebrow() const ; QString getFaceColor() const; QString getEyeColor() const; Qt::GlobalColor getColor(QString) const; void setSize(int) ; void setEyebrow(EyeBrowType) ; void setFaceColor(QString) ; void setEyeColor(QString) ; . . . }; ``` --- Una vez creado un objeto, sus métodos proveen la única forma de cambiar sus atributos, obtener información o hacer cómputos en los mismos. Es por esto que comúnmente se llama *interfaz* al conjunto de métodos de una clase. Los métodos son la interfaz entre el usuario de un objeto y su contenido. En general, en cada clase se definen los prototipos de los métodos para construir los objetos, y para buscar, manipular y guardar los datos. Lo siguiente es el formato general del prototipo de un método: `tipoDevolver nombreMetodo(tipo de los parámetros);` Luego, en el código del proyecto se escribe la función correspondiente al método, comenzando con un encabezado que incluye el nombre de la clase a la cuál pertenece la función: `TipoDevolver NombreClase::NombreMetodo(parámetros)` Para que los objetos que sean una instancia de una clase puedan tener acceso a las variables privadas de la clase se declaran métodos que sean públicos y que den acceso a estas clases (ver abajo "setters" y "getters"). Es preferible utilizar variables privadas y accederlas mediante los "setters" y "getters", a declararlas públicas ya que de esta manera el objeto que está asociado a estas variables tiene el control de los cambios que se hacen. Para invocar un método escribimos el nombre del objeto, seguido de un punto y luego el nombre del método: `nombreObjeto.nombreMetodo(argumentos);` #### Constructores Los primeros métodos de una clase que debemos entender son los *constructores*. Una clase puede tener múltiples constructores. Uno de los constructores será invocado automáticamente cada vez que se crea un objeto de esa clase. En la mayoría de los casos, los constructores se utilizan para inicializar los valores de los atributos del objeto. Para poder crear objetos de una clase, debemos conocer cuáles son sus constructores. En C++, los constructores tienen el mismo nombre que la clase. No se declara el tipo que devuelven porque estas funciones no devuelven ningún valor. Su declaración (incluida en la definición de la clase) es algo así: `nombreMetodo(tipo de los parámetros);` El encabezado de la función será algo así: `NombreClase::NombreMetodo(parámetros)` La clase `Bird` que estarás usando en la sesión de hoy tiene dos constructores (funciones sobrecargadas): `Bird (QWidget *parent=0)` `Bird (int, EyeBrowType, QString, QString, QWidget *parent=0)` Puedes ver las declaraciones de los prototipos de estos métodos en la declaración de la clase `Bird` en el archivo `bird.h` del proyecto. La documentación se encuentra en [este enlace] (http://ada.uprrp.edu/~ranazario/bird-html/class_bird.html). El primer constructor, `Bird (QWidget *parent=0)`, es un método que se puede invocar con uno o ningún argumento. Si al invocarlo no se usa argumento, el parámetro de la función toma el valor 0. El constructor de una clase que se puede invocar sin usar argumentos es el *constructor por defecto ("default")* de la clase; esto es, el constructor que se invoca cuando creamos un objeto usando una instrucción como: `Bird pitirre;` Puedes ver las implementaciones de los métodos de la clase Bird en el archivo `bird.cpp`. Nota que el primer constructor, `Bird (QWidget *parent=0)`, asignará valores aleatorios ("random") a cada uno de los atributos del objeto. Más adelante hay una breve explicación de la función `randInt`. Dale un vistazo a la documentación del segundo constructor, `Bird (int, EyeBrowType, QString, QString, QWidget *parent=0)`. Esta función requiere cuatro argumentos y tiene un quinto argumento que es opcional porque tiene un valor predeterminado. Una manera para usar este constructor es creando un objeto como el siguiente: `Bird guaraguao(200, Bird::UPSET, "blue", "red");` #### "Setters" ("mutators") Las clases proveen métodos para modificar los valores de los atributos de un objeto que se ha creado. Estos métodos se llaman "*setters*" o "*mutators*". Usualmente se declara un "setter" por cada atributo que tiene la clase. La clase `Bird` tiene los siguientes "setters": * `void setSize (int)` * `void setEyebrow (EyeBrowType)` * `void setFaceColor (QString)` * `void setEyeColor (QString)` Puedes ver las declaraciones de los métodos en la Figura 1 y en la declaración de la clase `Bird` en `bird.h`, y la implementación de algunos de los métodos en `bird.cpp`. El código en el siguiente ejemplo crea el objeto `bobo` de la clase `Bird` y luego cambia su tamaño a 333. ``` Bird bobo; bobo.setSize(333); ``` #### "Getters" ("accessors") Las clases también proveen métodos para acceder ("get") el valor del atributo de un objeto. Estos métodos se llaman "*getters*" o "*accessors*". Usualmente se declara un "getter" por cada atributo que tiene la clase. La clase `Bird` tiene los siguientes "getters": * `int getSize ()` * `EyeBrowType getEyebrow ()` * `QString getFaceColor ()` * `QString getEyeColor ()` Puedes ver las declaraciones de los métodos en la Figura 1 y en la declaración de la clase `Bird` en `bird.h`, y las implementaciones de algunos de métodos en `bird.cpp`. El código en el siguiente ejemplo crea el objeto `piolin` de la clase `Bird` e imprime su tamaño. ``` Bird piolin; cout << piolin.getSize(); ``` #### Otras funciones o métodos que utilizarás en esta experiencia de laboratorio **MainWindow:** El archivo `mainwindow.h` contiene la declaración de una clase llamada `MainWindow`. Los objetos que sean instancias de esta clase podrán utilizar los métodos sobrecargados `void MainWindow::addBird(int x, int y, Bird &b)` `void MainWindow::addBird(Bird &b)` que añadirán a la pantalla un dibujo del objeto de la clase `Bird` que es recibido como argumento. El código en el siguiente ejemplo crea un objeto `w` de la clase `MainWindow`, crea un objeto `zumbador` de la clase `Bird` y lo añade a la posición (200, 200) de la pantalla `w` usando el primer método. ``` MainWindow w; Bird zumbador; w.addBird(200, 200, zumbador); ``` --- ![figure1.png](images/figure1.png) **Figura 1.** Ventana `w` con la imagen del objeto `zumbador` en la posición (200, 200). --- **¡Importante!** No es suficiente solo crear los objetos `Bird` para que éstos aparezcan en la pantalla. Es necesario usar uno de los métodos `addBird` para que el dibujo aparezca en la pantalla. **randInt:** La clase `Bird` incluye el método `int Bird::randInt(int min, int max)` para generar números enteros aleatorios ("random") en el rango [min, max]. El método `randInt` depende de otra función para generar números aleatorios que requiere un primer elemento o *semilla* para ser evaluada. En este proyecto, ese primer elemento se genera con la invocación `srand(time(NULL)) ;`. --- --- !INCLUDE "../../eip-diagnostic/birds-objects/es/diag-birds-objects-01.html"
!INCLUDE "../../eip-diagnostic/birds-objects/es/diag-birds-objects-02.html"
!INCLUDE "../../eip-diagnostic/birds-objects/es/diag-birds-objects-03.html"
!INCLUDE "../../eip-diagnostic/birds-objects/es/diag-birds-objects-04.html"
!INCLUDE "../../eip-diagnostic/birds-objects/es/diag-birds-objects-05.html"
--- --- ## Sesión de laboratorio: En la experiencia de laboratorio de hoy, utilizarás la clase `Bird` para practicar la creación de objetos, acceder y cambiar sus atributos. ### Ejercicio 1 - Estudiar la clase `Bird` En este ejercicio te familiarizarás con la clase `Bird` y con algunos métodos asociados a la clase `MainWindow` que define la ventana en donde se despliegan resultados. #### Instrucciones 1. Carga a `QtCreator` el proyecto `Birds`. Hay dos maneras de hacer esto: * Utilizando la máquina virtual: Haz doble “click” en el archivo `Birds.pro` que se encuentra en el directorio `/home/eip/labs/objects-birds` de la máquina virtual. * Descargando la carpeta del proyecto de `Bitbucket`: Utiliza un terminal y escribe el comando `git clone http:/bitbucket.org/eip-uprrp/objects-birds` para descargar la carpeta `objects-birds` de `Bitbucket`. En esa carpeta, haz doble “click” en el archivo `Birds.pro`. 2. Estudia la clase `Bird` contenida en el archivo `bird.h`. Identifica los métodos que son constructores, "setters" y "getters". 3. En el archivo `main.cpp` (en Sources) la función `main` hace lo siguiente: a. Crea un objeto aplicación de Qt, llamado `a`. Lo único que necesitas saber sobre este objeto es que gracias a él es que podemos crear una aplicación gráfica en Qt e interaccionar con ella. b. Crea un objeto de la clase MainWindow llamado `w`. Este objeto corresponde a la ventana que verás cuando corras la aplicación. c. Inicializa la semilla del generador de números aleatorios de Qt. Esto hará que los pájaros nuevos tengan tamaños, colores y cejas aleatorias (a menos que los forcemos a tener valores específicos). d. Invoca el método `show()` al objeto `w`. Esto logra que se muestre la ventana donde se desplegarán los resultados. e. En los programas que no tienen interfaz gráfica, la función `main()` usualmente termina con la instrucción `return 0;`. En este proyecto se utiliza la instrucción `return a.exec();` para que el objeto `a` se haga cargo de la aplicación a partir de ese momento. 5. Ejecuta el programa marcando la flecha verde en el menú de la izquierda de la ventana de Qt Creator. El programa debe mostrar una ventana blanca. ### Ejercicio 2 - Crear objetos de clase `Bird` con ciertos atributos En este ejercicio crearás objetos de clase `Bird` usando el constructor por defecto y usando constructores donde defines características específicas para el objeto. También practicarás el uso de "getters" y "setters" para obtener y asignar atributos a los objetos. #### Instrucciones 1. Ahora crea un objeto de clase `Bird` llamado `abelardo` usando el constructor default y añádelo a la ventana `w` usando el método `addBird(int x, int y, Bird b)`. Recuerda que la invocación del método debe comenzar con el nombre del objeto `w` y un punto. 2. Corre varias veces el programa y maravíllate al ver a `abelardo` tener tamaños, colores y cejas distintas. 3. Utiliza los "setters" `setSize(int size)`, `setFaceColor(Qstring color)`, `setEyeColor(Qstring color)`, y `setEyebrow(EyeBrowType)` para que `abelardo` luzca como en la Figura 2 (su tamaño es 200). --- ![figure2.png](images/figure2.png) **Figura 2.** Abelardo. --- 4. Crea otro objeto de la clase Bird llamado `piolin` que tenga cara azul, ojos verdes, y cejas UNI invocando el constructor `Bird(int size, EyeBrowType brow, QString faceColor, QString eyeColor, QWidget *parent = 0)`. Su tamaño debe ser la mitad que el de `abelardo`. Añádelo a la misma ventana donde se muestra a `abelardo` usando `w.addBird(300, 100, piolin)` para obtener una imagen como la que se muestra en la Figura 3. --- ![figure3.png](images/figure3.png) **Figura 3.** Abelardo y Piolin. --- 5. Crea otros dos objetos llamados `juana` y `alondra` que salgan dibujados en las coordenadas (100, 300) y (300, 300) respectivamente. Crea a `juana` usando el constructor por defecto para que sus propiedades sean asignadas de forma aleatoria. Luego crea a `alondra` usando el otro constructor (el que recibe argumentos) para que puedas especificar sus propiedades durante su creación. `alondra` debe ser igual de grande que `juana`, tener el mismo tipo de cejas, y el mismo color de ojos. Su cara debe ser blanca. Añade a `alondra` y a `juana` a la misma ventana de `abelardo` y `piolin`. La ventana debe ser similar a la de la Figura 4. --- ![figure4.png](images/figure4.png) **Figura 4.** Abelardo, Piolín, Juana y Alondra. --- 6. Corre varias veces el programa para asegurarte que `alondra` y `juana` siguen pareciéndose en tamaño, cejas y ojos. --- --- ##Entregas Utiliza "Entrega" en Moodle para entregar el archivo `main.cpp` que contiene las invocaciones y cambios que hiciste al programa. Recuerda utilizar buenas prácticas de programación, incluye el nombre de los programadores y documenta tu programa. --- --- ##Referencias https://sites.google.com/a/wellesley.edu/wellesley-cs118-spring13/lectures-labs/lab-2