Unidad 5
Introducción 📜
Sección titulada «Introducción 📜»En esta unidad vas a profundizar en los principios fundamentales de la Programación Orientada a Objetos (OOP) usando C++. El objetivo es profundo: no solo usarás la herencia, el polimorfismo y el encapsulamiento en C++, sino que entenderás cómo funcionan por dentro, “bajo el capó”. Este conocimiento es lo que te permitirá, en el futuro, aprender cualquier otro lenguaje orientado a objetos, porque sabrás qué buscar y cómo funcionan los principios fundamentales.
Set: ¿Qué aprenderás en esta unidad? 💡
Sección titulada «Set: ¿Qué aprenderás en esta unidad? 💡»Reconozco que cada uno de ustedes llega a este punto con un bagaje distinto. Algunos se han dado por vencidos con la programación, otros han tenido experiencias frustrantes, y algunos han podido aprender. Por eso, en esta unidad, tú eliges el trayecto de aprendizaje. Te propongo dos rutas:
¿En qué consiste la ruta de exploración personal?
Tu misión es la misma: desentrañar los secretos de la OOP usando C++ como medio. Pero tú decides el mapa. El punto de partida es un diagnóstico.
Realizarás una breve actividad inicial. No es una prueba, es un espejo que te ayudará a ver qué conceptos manejas bien y cuáles son áreas de oportunidad.
Luego tú defines, basado en tu diagnóstico, tus propias preguntas. ¿Qué te genera más curiosidad? ¿Qué necesitas reforzar? Diseñarás tus experimentos
actuando como un científico computacional. Crearás pequeños programas, usarás el depurador y buscarás la evidencia que responda a tus preguntas. ES MUY IMPORTANTE
que sepas que en cualquiera de las dos rutas el error no es un fracaso, sino un dato valioso. No estamos apostando por el resultado final, sino por el proceso de aprendizaje.
Cada error es una oportunidad para aprender y crecer. Documenta tu Viaje en tu bitácora de aprendizaje, registrarás tu proceso. Una buena bitácora no solo
muestra código, muestra pensamiento: tus preguntas, hipótesis, experimentos (con capturas de pantalla), hallazgos, y reflexiones.
Seek: Investigación 🔎
Sección titulada «Seek: Investigación 🔎»Actividad 01
Sección titulada «Actividad 01»Esta será nuestra actividad de diagnóstico inicial
Parte 1: recordando los conceptos (en C#)
En tus cursos anteriores has trabajado principalmente con C#. Basándote en esa experiencia, responde con tus propias palabras:
- ¿Qué es el encapsulamiento para ti? Describe una situación en la que te haya sido útil o donde hayas visto su importancia.
- ¿Qué es la herencia? ¿Por qué un programador decidiría usarla? Da un ejemplo simple.
- ¿Qué es el polimorfismo? Describe con tus palabras qué significa que un código sea “polimórfico”.
Parte 2: análisis de código (en C#)
using System;using System.Collections.Generic;
public abstract class Figura{ private string nombre;
public string Nombre { get { return nombre; } protected set { nombre = value; } }
public Figura(string nombre) { this.Nombre = nombre; }
public abstract void Dibujar();}
public class Circulo : Figura{ public double Radio { get; private set; }
public Circulo(double radio) : base("Círculo") { this.Radio = radio; }
public override void Dibujar() { Console.WriteLine($"Dibujando un {Nombre} de radio {Radio}."); }}
public class Rectangulo : Figura{ public double Base { get; private set; } public double Altura { get; private set; }
public Rectangulo(double b, double h) : base("Rectángulo") { this.Base = b; this.Altura = h; }
public override void Dibujar() { Console.WriteLine($"Dibujando un {Nombre} de {Base}x{Altura}."); }}
public class Programa{ public static void Main() { List<Figura> misFiguras = new List<Figura>();
misFiguras.Add(new Circulo(5.0)); misFiguras.Add(new Rectangulo(4.0, 6.0)); misFiguras.Add(new Circulo(10.0));
foreach (Figura fig in misFiguras) { fig.Dibujar(); } }}Ahora, responde a estas preguntas sobre el código:
Encapsulamiento:
- Señala una línea de código que sea un ejemplo claro de encapsulamiento y explica por qué lo es.
- ¿Por qué crees que el campo nombre es private pero la propiedad Nombre es public? ¿Qué problema se evita con esto?
Herencia:
- ¿Cómo se evidencia la herencia en la clase Circulo?
- Un objeto de tipo Circulo, además de Radio, ¿Qué otros datos almacena en su interior gracias a la herencia?
Polimorfismo:
- Observa el bucle foreach. La variable fig es de tipo Figura, pero a veces contiene un Circulo y otras un Rectangulo. Cuando se llama a fig.Dibujar(), el programa ejecuta la versión correcta. En tu opinión, ¿Cómo crees que funciona esto “por debajo”? No necesitas saber la respuesta correcta, solo quiero que intentes razonar cómo podría ser.
Parte 3: hipótesis sobre la implementación
Esta es la parte más importante. Imagina que eres un diseñador de lenguajes de programación. Tienes que decidir cómo implementar estos conceptos en la memoria y en el procesador. No hay respuestas incorrectas, solo ideas. Dibuja si te ayuda.
-
Memoria y herencia: cuando creas un objeto Rectangulo, este tiene Base, Altura y también Nombre. ¿Cómo te imaginas que se organizan esos tres datos en la memoria del computador para formar un solo objeto?
-
El mecanismo del polimorfismo: pensemos de nuevo en la llamada fig.Dibujar(). El compilador solo sabe que fig es una Figura. ¿Cómo decide el programa, mientras se está ejecutando, si debe llamar al Dibujar del Circulo o al del Rectangulo? Lanza algunas ideas o hipótesis.
-
La barrera del encapsulamiento: ¿Cómo crees que el compilador logra que no puedas acceder a un miembro private desde fuera de la clase? ¿Es algo que se revisa cuando escribes el código, o es una protección que existe mientras el programa se ejecuta? ¿Por qué piensas eso?
Parte 4: y tu autoevaluación y primeras preguntas
Has completado el diagnóstico. Ahora, reflexiona sobre tu propia experiencia y basado en esto te propongo dos caminos:
- Formula la primer pregunta que comenzarás a investigar. Este será el punto de partida para tu “ruta de exploración personal”. Tu vas definiendo tus propiuas actividades.
- Si prefieres la “ruta guiada” adelante. Comienza con la actividad 2.
Actividad 02
Sección titulada «Actividad 02»En esta actividad te mostraré una aplicación para que veas aplicados todos los conceptos que estudiarás en esta unidad.
Durante la actividad te indicaré los momentos en los que debes detenerte para analizar 🧐, experimentar 🧪 y reportar ✍️ tus hallazgos en la bitácora de aprendizaje.
Crea un proyecto en openFrameworks y adiciona el siguiente código.
ofApp.h
#pragma once#include "ofMain.h"#include <vector>
// -------------------------------------------------// Clase base abstracta: Particle// -------------------------------------------------class Particle {public: virtual ~Particle() {} virtual void update(float dt) = 0; virtual void draw() = 0; virtual bool isDead() const = 0; // Nuevo método para saber si la partícula (tipo RisingParticle) debe explotar virtual bool shouldExplode() const { return false; } // Métodos para obtener posición y color, para usarlos en explosiones virtual glm::vec2 getPosition() const { return glm::vec2(0, 0); } virtual ofColor getColor() const { return ofColor(255); }};
// -------------------------------------------------// RisingParticle: Partícula que nace en la parte inferior central y sube// -------------------------------------------------class RisingParticle : public Particle {protected: glm::vec2 position; glm::vec2 velocity; ofColor color; float lifetime; // tiempo máximo antes de explotar float age; bool exploded;public: RisingParticle(const glm::vec2& pos, const glm::vec2& vel, const ofColor& col, float life) : position(pos), velocity(vel), color(col), lifetime(life), age(0), exploded(false) { }
void update(float dt) override { position += velocity * dt; age += dt; // Aumenta la desaceleración para dar sensación de recorrido largo velocity.y += 9.8f * dt * 8; // Condición de explosión: cuando la partícula alcanza aproximadamente el 15% de la altura float explosionThreshold = ofGetHeight() * 0.15 + ofRandom(-30, 30); if (position.y <= explosionThreshold || age >= lifetime) { exploded = true; } }
void draw() override { ofSetColor(color); // Partícula más grande ofDrawCircle(position, 10); }
bool isDead() const override { return exploded; } bool shouldExplode() const override { return exploded; } glm::vec2 getPosition() const override { return position; } ofColor getColor() const override { return color; }};
// -------------------------------------------------// Clase base para explosiones: ExplosionParticle// -------------------------------------------------class ExplosionParticle : public Particle {protected: glm::vec2 position; glm::vec2 velocity; ofColor color; float age; float lifetime; float size; // tamaño de la partícula de explosiónpublic: ExplosionParticle(const glm::vec2& pos, const glm::vec2& vel, const ofColor& col, float life, float sz) : position(pos), velocity(vel), color(col), age(0), lifetime(life), size(sz) { }
void update(float dt) override { position += velocity * dt; age += dt; float alpha = ofMap(age, 0, lifetime, 255, 0, true); color.a = alpha; }
bool isDead() const override { return age >= lifetime; }};
// -------------------------------------------------// CircularExplosion: Explosión en patrón circular// -------------------------------------------------class CircularExplosion : public ExplosionParticle {public: CircularExplosion(const glm::vec2& pos, const ofColor& col) : ExplosionParticle(pos, glm::vec2(0, 0), col, 1.2f, ofRandom(16, 32)) { float angle = ofRandom(0, TWO_PI); float speed = ofRandom(80, 200); velocity = glm::vec2(cos(angle), sin(angle)) * speed; }
void draw() override { ofSetColor(color); ofDrawCircle(position, size); }};
// -------------------------------------------------// RandomExplosion: Explosión con direcciones aleatorias// -------------------------------------------------class RandomExplosion : public ExplosionParticle {public: RandomExplosion(const glm::vec2& pos, const ofColor& col) : ExplosionParticle(pos, glm::vec2(0, 0), col, 1.5f, ofRandom(16, 32)) { velocity = glm::vec2(ofRandom(-200, 200), ofRandom(-200, 200)); }
void draw() override { ofSetColor(color); ofDrawRectangle(position.x, position.y, size, size); }};
// -------------------------------------------------// StarExplosion: Explosión en forma de estrella// -------------------------------------------------class StarExplosion : public ExplosionParticle {public: StarExplosion(const glm::vec2& pos, const ofColor& col) : ExplosionParticle(pos, glm::vec2(0, 0), col, 1.3f, ofRandom(20, 40)) { float angle = ofRandom(0, TWO_PI); float speed = ofRandom(90, 180); velocity = glm::vec2(cos(angle), sin(angle)) * speed; }
void draw() override { ofSetColor(color); int rays = 5; float outerRadius = size; float innerRadius = size * 0.5; ofPushMatrix(); ofTranslate(position); for (int i = 0; i < rays; i++) { float theta = ofMap(i, 0, rays, 0, TWO_PI); float xOuter = cos(theta) * outerRadius; float yOuter = sin(theta) * outerRadius; float xInner = cos(theta + PI / rays) * innerRadius; float yInner = sin(theta + PI / rays) * innerRadius; ofDrawLine(0, 0, xOuter, yOuter); ofDrawLine(xOuter, yOuter, xInner, yInner); } ofPopMatrix(); }};
// -------------------------------------------------// ofApp: Manejo de la escena y eventos// -------------------------------------------------class ofApp : public ofBaseApp {public: void setup(); void update(); void draw(); void mousePressed(int x, int y, int button); void keyPressed(int key);
std::vector<Particle*> particles; ~ofApp();
private: void createRisingParticle();
};ofApp.cpp
#include "ofApp.h"
// --------------------------------------------------------------void ofApp::setup() { ofSetFrameRate(60); ofBackground(0);}
// --------------------------------------------------------------void ofApp::update() { float dt = ofGetLastFrameTime();
// Actualiza todas las partículas for (int i = 0; i < particles.size(); i++) { particles[i]->update(dt); }
// Procesa las partículas (iteración en reversa para facilitar eliminación) for (int i = particles.size() - 1; i >= 0; i--) { // Si la partícula debe explotar, generamos nuevas explosiones if (particles[i]->shouldExplode()) { int explosionType = (int)ofRandom(3); // 0: Circular, 1: Random, 2: Star int numParticles = (int)ofRandom(20, 30); for (int j = 0; j < numParticles; j++) { if (explosionType == 0) { particles.push_back(new CircularExplosion(particles[i]->getPosition(), particles[i]->getColor())); } else if (explosionType == 1) { particles.push_back(new RandomExplosion(particles[i]->getPosition(), particles[i]->getColor())); } else { particles.push_back(new StarExplosion(particles[i]->getPosition(), particles[i]->getColor())); } } delete particles[i]; particles.erase(particles.begin() + i); } else if (particles[i]->isDead()) { delete particles[i]; particles.erase(particles.begin() + i); } }}
// --------------------------------------------------------------void ofApp::draw() { for (int i = 0; i < particles.size(); i++) { particles[i]->draw(); }}
// --------------------------------------------------------------void ofApp::createRisingParticle() { // Genera una RisingParticle cerca del centro inferior (con variación horizontal) float minX = ofGetWidth() * 0.35; float maxX = ofGetWidth() * 0.65; float spawnX = ofRandom(minX, maxX); glm::vec2 pos(spawnX, ofGetHeight()); // La partícula apunta hacia un objetivo en la parte superior central glm::vec2 target(ofGetWidth() / 2 + ofRandom(-300, 300), ofGetHeight() * 0.10 + ofRandom(-30, 30)); glm::vec2 direction = glm::normalize(target - pos); // Velocidad ajustada para recorrer una mayor distancia glm::vec2 vel = direction * ofRandom(250, 350); ofColor col; col.setHsb(ofRandom(255), 220, 255); float lifetime = ofRandom(1.5, 3.5); // Tiempo de vida antes de explotar particles.push_back(new RisingParticle(pos, vel, col, lifetime));}
// --------------------------------------------------------------void ofApp::mousePressed(int x, int y, int button) { createRisingParticle();}
// --------------------------------------------------------------void ofApp::keyPressed(int key) { if (key == ' ') { for (int i = 0; i < 1000; i++) { createRisingParticle(); } } if (key == 's') { ofSaveScreen("screenshot_" + ofToString(ofGetFrameNum()) + ".png"); }}
// --------------------------------------------------------------ofApp::~ofApp() { for (int i = 0; i < particles.size(); i++) { delete particles[i]; } particles.clear();}🧐🧪✍️ Analiza el código de la aplicación y trata de explicar en tus propias palabras qué está haciendo, NO USES IA generativa. Captura pantallas de la aplicación funcionando y añádelas a la bitácora de aprendizaje.
Cuando ejecutes la aplicación deberías ver algo como esto:




Actividad 03
Sección titulada «Actividad 03»Ahora te guiaré en el análisis del caso de estudio anterior. En esta actividad
vas a recordar y sobre todo a redescubrir algunos conceptos fundamentales de la programación orientada a objetos, pero
esta vez lo harás desde la experimentación y la curiosidad. Quiero insistir en esto. En cursos previos ya abordaste teóricamente estos conceptos e
incluso los aplicaste en ejercicios prácticos. Sin embargo, en esta actividad vas a experimentar con el caso de estudio y con el depurador de código para
que puedas comprender mejor cómo se comportan los objetos en un programa y cómo se implementan algunos conceptos como la herencia, el polimorfismo y
el encapsulamiento.
Concepto de objeto: en la programación orientada a objetos, un objeto es una instancia de una clase. Una clase define un tipo de objeto, pero no es un objeto en sí mismo. Pero ¿Cómo se ve un objeto en la memoria?
Considera el caso de estudio. Usa el depurador para encontrar la instancia
de la clase ofApp. Recuerda que debes usar el depurador porque el objeto solo estará en la memoria mientras la aplicación esté corriendo.
Antes de comenzar el experimento observa la clase ofApp:
class ofApp : public ofBaseApp {public: void setup(); void update(); void draw(); void mousePressed(int x, int y, int button); void keyPressed(int key);
std::vector<Particle*> particles; ~ofApp();
private: void createRisingParticle();
};🧐🧪✍️ Antes de ejecutar el experimento, ¿Qué esperas ver en memoria (hipótesis)? Ejecuta el código y muestra una captura de pantalla del objeto en la memoria. ¿Qué puedes observar? ¿Qué información te proporciona el depurador? ¿Qué puedes concluir?
🧐🧪✍️ Usa de nuevo el depurador para capturar un objeto de tipo CircularExplosion. Es posible que tengas que hacer
modificaciones mínimas en el código para que puedas capturar este objeto más fácilmente. Observa con el depurador la ventana
de Auto o Locals y la ventana de Memory 1. Trata de buscar en memoria todas las partes que componen al objeto tipo CircularExplosion
¿Qué puedes observar en la memoria? ¿Qué información te proporciona el depurador? ¿Qué puedes concluir? NO OLVIDES tener a la mano todas
la jerarquía de clases que componen a CircularExplosion. De esta manera podrás identificar cada parte del objeto en memoria.
Concepto de los métodos virtuales: observa de nuevo en memoria un objeto de tipo CircularExplosion. Nota que el primer campo en memoria del objeto
es un ExplosionParticle. Abren el objeto ExplosionParticle y observa que el primer campo en memoria es un Particle. Abre el objeto Particle
y observa que el primer campo en memoria es _vtable. ¿Qué es eso? Es un puntero a una tabla de funciones virtuales. Observa detenidamente la tabla de funciones.
🧐🧪✍️ Captura la _vtable de un objeto CircularExplosion, pega la imagen en tu bitácora, pero observa detenidamente la tabla de funciones. ¿Qué puedes observar?
Te voy a mostrar un ejemplo, en mi caso, de cómo se ve la tabla de funciones:

🧐🧪✍️ Ahora, captura en memoria la _vtable de un objeto StarExplosion,
pega la imagen en tu bitácora y observa detenidamente la tabla de funciones.
Te muestro de nuevo el ejemplo, en mi caso, de cómo se ve la tabla de funciones:

🧐🧪✍️ Observa de nuevo ambas tablas y compara. ¿Qué puedes ver? ¿Qué puedes concluir? ¿Qué relación existe entre la tabla de funciones y los métodos virtuales? Esta pregunta que te voy a hacer no es fácil y la idea de hacerla es prepararte mentalmente para lo viene ¿Para qué crees que pueda servir una tabla de funciones virtuales? Para responder esta pregunta trata de pensar en el polimorfismo con interfaces y clases abstractas que viste al estudiar C#, por ejemplo, con interfaces:
using System;
interface IAnimal{ void HacerSonido();}
class Perro : IAnimal{ public void HacerSonido() { Console.WriteLine("El perro ladra: ¡Guau, guau!"); }}
class Gato : IAnimal{ public void HacerSonido() { Console.WriteLine("El gato maúlla: ¡Miau, miau!"); }}
class Program{ static void Main() { // Polimorfismo: Usamos la interfaz para tratar diferentes tipos de animales IAnimal[] animales = new IAnimal[] { new Perro(), new Gato() };
foreach (IAnimal animal in animales) { animal.HacerSonido(); // Llamada polimórfica } }}Nota que el método HacerSonido se llama dos veces, una vez para
el perro y otra vez para el gato. ¿Cómo se logra esto? ¿Qué relación
existe entre los métodos virtuales y el polimorfismo? Al llamar HacerSonido
cómo sabe esta función sobre cuál objeto debe actuar?
Dejemos por ahora este experimento hasta este punto, pero un rato lo vamos retomar.
Actividad 04
Sección titulada «Actividad 04»Concepto de encapsulamiento: el encapsulamiento es un concepto fundamental en la programación orientada a objetos. En C++ el encapsulamiento se logra mediante el uso de modificadores de acceso. Te voy a proponer un experimento que puedes implementar creando un proyecto de consola de C++ en Visual Studio.
class AccessControl {
private: int privateVar;
protected: int protectedVar;
public: int publicVar; AccessControl() : privateVar(1), protectedVar(2), publicVar(3) {}};
int main() { AccessControl ac; ac.publicVar = 10; // Válido // ac.protectedVar = 20; // Error de compilación // ac.privateVar = 30; // Error de compilación return 0;}Ejecuta este código. Luego, descomenta las líneas que están comentadas y vuelve a compilar. ¿Qué sucede? ¿Por qué sucede esto? ¿Qué puedes concluir?
Ahora quiero que notes algo. El encapsulamiento solo lo podemos garantizar en tiempo de compilación. Sin embargo, en tiempo de ejecución podemos acceder a los campos privados de un objeto. Analiza el siguiente programa:
#include <iostream>
class MyClass {private: int secret1; float secret2; char secret3;
public: MyClass(int s1, float s2, char s3) : secret1(s1), secret2(s2), secret3(s3) {}
void printMembers() const { std::cout << "secret1: " << secret1 << "\n"; std::cout << "secret2: " << secret2 << "\n"; std::cout << "secret3: " << secret3 << "\n"; }};
int main() { MyClass obj(42, 3.14f, 'A'); // Esta línea causará un error de compilación std::cout << obj.secret1 << std::endl;
obj.printMembers(); // Método público para mostrar los valores return 0;}🧐🧪✍️ Compila el programa. ¿Qué pasa?
Ahora prueba con este programa:
#include <iostream>
class MyClass {private: int secret1; float secret2; char secret3;
public: MyClass(int s1, float s2, char s3) : secret1(s1), secret2(s2), secret3(s3) {}
void printMembers() const { std::cout << "secret1: " << secret1 << "\n"; std::cout << "secret2: " << secret2 << "\n"; std::cout << "secret3: " << secret3 << "\n"; }};
int main() { MyClass obj(42, 3.14f, 'A');
// Usando reinterpret_cast para violar el encapsulamiento int* ptrInt = reinterpret_cast<int*>(&obj); float* ptrFloat = reinterpret_cast<float*>(ptrInt + 1); char* ptrChar = reinterpret_cast<char*>(ptrFloat + 1);
// Accediendo y mostrando los valores privados std::cout << "Accediendo directamente a los miembros privados:\n"; std::cout << "secret1: " << *ptrInt << "\n"; // Accede a secret1 std::cout << "secret2: " << *ptrFloat << "\n"; // Accede a secret2 std::cout << "secret3: " << *ptrChar << "\n"; // Accede a secret3
return 0;}🧐🧪✍️ Compila el programa y ejecuta. ¿Qué puedes concluir?
🧐🧪✍️ En tus palabras, ¿Qué es el encapsulamiento? ¿Por qué es importante?
Actividad 05
Sección titulada «Actividad 05»Concepto de herencia: la herencia es otro concepto fundamental en la programación
orientada a objetos. Observa de nuevo en ofApp.h la clase CircularExplosion. Observa
que esta clase hereda de la clase ExplosionParticle que a su vez hereda de la clase
Particle.
🧐🧪✍️ captura de nuevo la memoria que ocupa el objeto CircularExplosion compara
la jerarquía de clases con los campos en memoria del objeto. ¿Qué puedes observar?
¿Qué información te proporciona el depurador? ¿Qué puedes concluir?
🧐🧪✍️ ¿Cómo se implementa la herencia en C++?
🧐🧪✍️ C++ permite hacer algo que C# no: herencia múltiple. Realiza un experimento que te permita ver cómo se objeto en memoria cuya clase base tiene herencia múltiple.
Actividad 06
Sección titulada «Actividad 06»Concepto de polimorfismo: recuerdas que ya analizaste el concepto de los métodos virtuales y su relación con la tabla de funciones virtuales. Ahora quiero que pienses en el polimorfismo.
Observa en ofApp.cpp en el método update() esta parte del código:
// Actualiza todas las partículas for (int i = 0; i < particles.size(); i++) { particles[i]->update(dt); }el método update de la clase Particle es un método virtual. Usa el depurador
para analizar cómo se comporta este método en tiempo de ejecución. Realiza
esta verificación cuando particles tenga varios objetos de diferentes tipos
de partículas. ¿Qué puedes observar? ¿Qué información te proporciona el depurador?
Nota que update se comporta de manera diferente para cada tipo de partícula. A esto se le llama polimorfismo en tiempo de ejecución.
🧐🧪✍️ Realiza un dibujo con el cuál expliques cómo se implementa el polimorfismo en tiempo de ejecución. Utiliza el concepto de métodos virtuales y la tabla de funciones virtuales. ¿Qué puedes concluir?
🧐🧪✍️ ¿Qué relación existe entre los métodos virtuales y el polimorfismo?
Apply: Aplicación 🛠
Sección titulada «Apply: Aplicación 🛠»Actividad 07
Sección titulada «Actividad 07»Aplica lo aprendido. Vas a evaluar lo aprendido en la fase anterior modificando el caso de estudio.
⚠️ IMPORTANTE: si usas IA generativa no le pidas respuestas. La idea de esta sección es que apliques lo aprendido. Si no sabes cómo hacerlo, quiere decir que aún tienes vacíos en tu aprendizaje y debes regresar a la fase anterior o solicitar ayuda al profesor antes de continuar.
¿Qué harás?
- Agrega dos nuevos tipos de Particle diferentes a RisingParticle.
- Implementar un nuevo modo de explosión.
Reporta en tu bitácora de aprendizaje:
- ¿Cómo y por qué de la implementación de cada una de las extensiones solicitadas al caso de estudio?
- ¿Cómo y por qué de la implementación de los conceptos de encapsulamiento, herencia y polimorfismo en tu código?
- Explica cómo verificaste que cada una de las extensiones funciona correctamente, muestra capturas de pantalla del depurador donde evidencias lo anterior, en particular el polimorfismo en tiempo de ejecución.
Evidencias 🗂️
Sección titulada «Evidencias 🗂️»Reflect: Consolidación y metacognición 🤔
Sección titulada «Reflect: Consolidación y metacognición 🤔»Es momento de hacer una de las fases más importantes del aprendizaje: la reflexión.
- En una hoja de papel o un white board digital te pediré que hagas un inventario de los conceptos de las unidades 1 a la 5. Luego construye un diagrama donde ubiques todos los conceptos tratando de agruparlos y relacionarlos entre sí.
- Pregúntate: ¿Qué conceptos domino bien? ¿Cuáles me cuestan más trabajo?
- Pregúntate para qué pueden servirte estos conceptos.
- ¿Qué hiciste bien en esta unidad que debes continuar haciendo?
- ¿Qué deberías comenzar a hacer para mejorar tu proceso?
- Formula tu plan de acción personal para abordar aquello que te cueste más trabajo.