Está en la página 1de 19

UCSM Esc. Prof.

de Ingeniería de Sistemas

2023
INFORME DE PRÁCTICAS

LENGUAJES DE
PROGRAMACIÓN II

© IEEE 2013 The Institute of Electrical and Electronics Engineers, Inc.


Lenguajes de Programación II practica-08 grupo 02
Actividad N° 08

CÓDIGO APELLIDOS Y NOMBRES FECHA


2022221882 GARZÓN MENDOZA ANA PAULA VIVIANA 25/05/2023
2022241081 BALDÁRRAGO SAMATELO, PERO FERNANDI 25/05/2023
2022222271 CAZORLA MACEDO IRVIN ESTUARDO 25/05/2023

Introducción
En el ámbito de la programación orientada a objetos (POO), se encuentran varios principios fundamentales que
posibilitan el diseño de sistemas más flexibles, modulares y fáciles de mantener. En este capítulo, examinaremos
cuatro de estos conceptos clave: Clases Abstractas, Interfaces, Funciones Virtuales y Remplazo/Refinamiento.

Iniciaremos comprendiendo qué son las Clases Abstractas y las Interfaces, y cómo se utilizan para establecer una base
común en la jerarquía de clases y definir contratos para las clases derivadas. Posteriormente, nos adentraremos en el
mundo de las Funciones Virtuales y cómo posibilitan el polimorfismo al permitir la redefinición de comportamientos
en las clases hijas. Finalmente, exploraremos los conceptos de Remplazo y Refinamiento, y cómo contribuyen a
mantener la coherencia y flexibilidad en la evolución de nuestros sistemas.

A lo largo de este capítulo, analizaremos ejemplos prácticos y estudiaremos cómo estos conceptos se aplican en
diferentes lenguajes de programación orientados a objetos, tales como C++, Java, Python y JavaScript. Observaremos
cómo cada uno de estos conceptos se emplea para resolver problemas del mundo real y cómo nos facilitan la escritura
de código más modular, reutilizable y mantenible.

Resumen
En este capítulo, hemos explorado cuatro conceptos fundamentales en la programación orientada a objetos: Clases
Abstractas, Interfaces, Funciones Virtuales y Remplazo/Refinamiento.

Las Clases Abstractas nos permiten definir una clase base que no puede ser instanciada directamente, pero establece
una base común para las clases derivadas. Por otro lado, las Interfaces nos permiten definir un conjunto de métodos
que deben ser implementados por las clases que las utilicen.

Las Funciones Virtuales nos brindan la capacidad de redefinir comportamientos en las clases derivadas, lo que facilita
el logro de polimorfismo y la escritura de código más genérico y flexible. Por último, el Remplazo y Refinamiento nos
ayudan a mantener la coherencia y flexibilidad en la evolución de nuestros sistemas, permitiéndonos reemplazar o
mejorar comportamientos en las clases derivadas.

A lo largo del capítulo, hemos analizado ejemplos prácticos y hemos visto cómo estos conceptos se aplican en
diferentes lenguajes de programación orientados a objetos. Hemos descubierto cómo nos ayudan a resolver
problemas del mundo real y a escribir código más modular, reutilizable y mantenible.

En el próximo capítulo, nos sumergiremos en el tema de los Patrones de Diseño en la programación orientada a
objetos. Exploraremos soluciones comunes a problemas recurrentes y proporcionaremos pautas para escribir
software más robusto y escalable.
MARCO TEÓRICO
1.1 Clases abstractas
¿QUÉ ES? ¿CÓMO SE DECLARA? ¿CÓMO LO USO? ¿CUÁNDO LO USO?

Es la que no instancia / Fig. 25.01: unaclaseabstracta.h Se debe crear una clase hija Se utiliza una clase abstracta
objetos, para tal caso // Declaración de la clase que herede de ella. La clase cuando se desea definir una
se debe evitar que abstracta, se declara método hija debe proporcionar una estructura común y establecer
funcionalmente una virtual puro. implementación para todos un contrato para las clases
clase así no pueda #ifndef los métodos abstractos derivadas. La clase abstracta
hacerlo, esto se UNACLASEABSTRACTA_H definidos en la clase puede contener métodos y
consigue creando #define abstracta. propiedades que son
métodos virtuales UNACLASEABSTRACTA_H compartidos por todas las clases
puros, para convertir Class UnaClaseAbstracta derivadas, proporcionando así
a un método en un {} una base sólida para la herencia
método virtual puro public:
se le iguala a cero en
la declaración, esto UnaClaseAbstracta(int,char,float);
hace que no pueda ser void ingreso();
definida en la clase void salida();
donde se declara. // método virtual puro
virtual void
metodoVirtualPuro() = 0;
int getAtributoEntero();
float getAtributoFloat();
char getAtributoChar();
private:
int atributoEntero;
char atributochar;
float atributoFloat;
};
#endif

1.2 Reglas de uso

¿QUÉ ES? ¿CÓMO SE DECLARA? ¿CÓMO LO USO? ¿CUÁNDO LO USO?


Es una clase que no Se utiliza la palabra public class MiClaseHija extends Cuando se desea establecer una
se puede instanciar clave "abstract" antes MiClaseAbstracta { estructura común y definir un
directamente y se de la palabra clave // Implementación de métodos conjunto de métodos que deben
utiliza como una "class" al definir la abstractos y otros miembros ser implementados por las clases
base para derivar clase. } derivadas.
clases hijas.
1.3 ¿Qué es una clase Completamente Abstracta?

¿QUÉ ES? ¿CÓMO SE DECLARA? ¿CÓMO LO USO? ¿CUÁNDO LO USO?

Es una clase que solo contiene Varia según el lenguaje de C++ : Cuando se desea definir un
como miembros a métodos programación. class MiClaseHija : public contrato o interfaz que las
virtuales puros, al usarse el En el caso de una clase MiClaseAbstracta { clases concretas deben
mecanismo de separación de la abstracta en C++, se utiliza public: cumplir. Se utiliza para
definición de clase ya la la palabra clave "override" void miMetodo() override { establecer un conjunto de
implementación de métodos d En el caso de una interfaz en // Implementación del métodos que deben ser
forma externa a la clase Java, se utiliza la palabra método abstracto implementados por las
caeremos en la cuenta que no clave "implements" para } clases que la implementan,
se necesita de un archivo .cpp implementar la interfaz en }; sin proporcionar ninguna
una clase. implementación
Java: predeterminada.
public class MiClase
implements MiInterfaz {
// Implementación de los
métodos abstractos de la
interfaz
}

1.4 ¿Cómo se implementa una clase completamente abstracta?

¿QUÉ ES? ¿CÓMO SE DECLARA? ¿CÓMO LO USO? ¿CUÁNDO LO USO?

Lo primero que conviene // Fig. 26.01: unaclase.h La clase anterior será usada como clase Cuando se desea definir un
recordar es que C++ no // Declaración de una base convencional, aquí no existen contrato o interfaz que las
dispone de interfaces", y clase cualquiera para métodos virtuales puros, por lo que clases concretas deben
lo que vamos a hacer es herencia dicha clase no es abstracta. Veamos cumplir. Se utiliza para
simular los mismos por #ifndef UNACLASE_H ahora cómo queda el archivo establecer un conjunto de
medio de "clases #define UNACLASE_H "unaclase.cpp”. métodos que deben ser
completamente ClassUnaClase implementados por las
abstractas". { clases que la implementan,
Public: sin proporcionar ninguna
UnaClase(int,char,float); implementación
void ingreso(); predeterminada.
void salida();
int getAtributoEntero();
float getAtributoFloat();
char getAtributoChar();
private:
int atributoEntero;
char atributochar;
float atributoFloat;
};
#endif
1.5 ¿Cómo se declara un método virtual?
¿QUÉ ES? ¿CÓMO SE DECLARA? ¿CÓMO LO USO? ¿CUÁNDO LO USO?

Es un concepto de virtual void metodo(); // Fig. 27.01: clasebase.h Es especialmente útil en


la programación // Declaración de la clase base con el contexto de la herencia
orientada a objetos métodos virtuales y el polimorfismo en la
que permite que un #ifndef CLASEBASE_H programación orientada a
método en una clase #define CLASEBASE_H objetos.
base pueda ser class ClaseBase
redefinido en una {
clase derivada. Un public:
método virtual ClaseBase(int i) : atributoEntero(i)
proporciona una {
implementación }
base en la clase // Métodos virtuales
base, pero permite virtual void metodo1();
que las clases virtual int metodo2();
derivadas virtual int metodo3(int);
proporcionen su virtual void metodo4(int);
propia private:
implementación int atributoEntero;
personalizada };
#endif

1.5 Invocación en jerarquías de clases

¿QUÉ ES? ¿CÓMO SE DECLARA? ¿CÓMO LO USO? ¿CUÁNDO LO USO?


Cuando una clase // Fig. 27.04: ejecutar.cpp Crear una instancia de una Se utiliza en situaciones donde
base tiene una // Demostración de interfaces clase derivada: se requiere polimorfismo y se
función virtual y #include <iostream>
using namespace std; desea que los métodos en las
una clase derivada Llamar al método mediante un clases derivadas se ejecuten
#include "clasebase.h"
de forma pública de
#include "clasederivada.h" puntero o una referencia a la según el tipo concreto del
ésta tiene la misma int main() clase base: objeto en tiempo de ejecución.
función {
implementada, al ClaseBase *ptrClaseBase; MiClaseBase* objeto = new
hacer una llamada ClaseDerivada MiClaseDerivada();
al método mediante objClaseDerivada(3); objeto->miMetodo(); //
uno bjeto de la ClaseDerivada Llamada al método virtual
clase derivada, esta *ptrClaseDerivada = new
invocación ClaseDerivada(6);
ejecutara al método ClaseBase &refClaseBase =
objClaseDerivada;
virtual de la clase
ptrClaseBase =
derivada aun así se &objClaseDerivada;
haga mediante objClaseDerivada.metodo1();
punteros o ptrClaseDerivada ->
referencias. metodo1();
ptrClaseBase -> metodo1();
refClaseBase.metodo1();
system("pause");
return 0;
}

1.6 Tabla de funciones virtuales

¿QUÉ ES? ¿CÓMO SE DECLARA? ¿CÓMO LO USO? ¿CUÁNDO LO USO?

Cuando se trata de Es gestionada por el s transparente para el Se utiliza cuando se desea lograr
métodos virtuales el compilador y no requiere programador y se maneja el polimorfismo y el
compilador debe una declaración explícita de forma interna por el comportamiento dinámico de
vincular la dirección por parte del programador. compilador y el tiempo de los métodos virtuales en una
del método con el ejecución del lenguaje de jerarquía de clases.
objeto invocado, pero programación. Al utilizar 1. Sustitución de objetos:
esto no es posible ya polimorfismo y llamar a 2. Polimorfismo
que únicamente en un método virtual en un 3. Implementación
tiempo de ejecución objeto, el compilador específica de clases
sabremos quién en utiliza la tabla de derivadas:
realidad invoca al funciones virtuales para
método, para determinar la
solucionar este implementación correcta
problema se crea una del método según el tipo
tabla llamada vtable, de objeto concreto.
donde cada objeto de
la clase derivada debe
incluir un puntero a
dicha tabla de
direcciones de
métodos virtuales.

1.7 Tipos devueltos por las funciones virtuales


¿QUÉ ES? ¿CÓMO SE DECLARA? ¿CÓMO LO USO? ¿CUÁNDO LO USO?

Al redefinirse un // Fig. 27.05: otraclase.h Se llama al método virtual Depende de los


método virtual no se // Declaración de una clase utilizando un puntero o una requisitos y la lógica
puede cambiarse el base cualquiera para herencia referencia a la clase base específica de la
tipo de valor de #ifndef aplicación.
retorno. Al hacer OTRACLASEBASE_H MiClaseBase* objeto = new 1. Declarar el tipo
dicho proceso la #define MiClaseDerivada(); correcto
firma del método OTRACLASEBASE_H int resultado = objeto- 2. Utilizar el
debe ser idéntica. class OtraClaseBase >miMetodo(); // Llamada al resultado de
{
public: método virtual y asignación del forma
OtraClaseBase(int i) : resultado coherente
atributoEntero(i) . 3. Considerar la
{ coherencia con
}
la jerarquía de
private:
int atributoEntero; clases
};
#endif

1. 8 AÑADIR

¿QUÉ ES? ¿CÓMO SE DECLARA? ¿CÓMO LO USO? ¿CUÁNDO LO USO?


Se refiere a la Se declara y define directamente en la clase ClaseDerivada objeto; Se utiliza en situaciones
capacidad de derivada. No es necesario modificar la clase objeto.nuevoMetodo(); donde se necesita
agregar base ni realizar ninguna declaración // Llamada al nuevo extender las
nuevos especial. método en la instancia capacidades de una
métodos o de la clase derivada clase derivada sin
atributos a C++ modificar la clase base
class ClaseBase {
una clase
public: ni afectar a otras clases
derivada sin // Métodos y atributos de la clase base derivadas.
modificar la };
clase base ni Ampliar funcionalidad
afectar a otras class ClaseDerivada : public ClaseBase {
public: .
clases void nuevoMetodo() { Especialización de
derivadas. // Implementación del nuevo método en la clase funcionalidad.
derivada
}
};
Personalización de
comportamiento.

1.7 REEMPLAZO
¿QUÉ ES? ¿CÓMO SE DECLARA? ¿CÓMO LO USO? ¿CUÁNDO LO USO?
Cuando se llevan a Se utiliza la técnica de la ClaseBase* objeto = new Se utiliza cuando se
cabo implantaciones sobreescritura de métodos. ClaseDerivada(); necesita modificar
de reemplazo y Esto implica declarar un objeto->miMetodo(); // completamente el
refinamiento se método con la misma firma Llamada al método comportamiento de
choca con la (nombre, parámetros y tipo reemplazado en la un método heredado
dificultad de poder devuelto) en la clase instancia de la clase en una clase derivada.
preservar las derivada. derivada
características del Personalización del
tipo de relación es- class ClaseBase { comportamiento.
un. Esto es, al anular public:
un método, virtual void miMetodo() { Modificación de
generalmente no se // Implementación de la funcionalidad.
tiene garantía alguna clase base
de que el } Polimorfismo.
comportamiento };
exhibido por la clase
derivada tendrá class ClaseDerivada : public
alguna relación con el ClaseBase {
de la clase base. public:
void miMetodo() override
{
// Nueva
implementación en la clase
derivada
}
};

1. 8 REFINAMIENTO
¿QUÉ ES? ¿CÓMO SE DECLARA? ¿CÓMO LO USO? ¿CUÁNDO LO USO?

se refiere a la Se realiza mediante la class ClaseBase { Se utiliza en situaciones


capacidad de una sobrescritura parcial del public: donde se necesita ajustar o
clase derivada de método heredado en la virtual void miMetodo() { modificar parcialmente el
modificar o ajustar clase derivada. Esto // Implementación de la comportamiento de un
parcialmente el implica declarar un clase base método heredado en una
comportamiento de método con la misma } clase derivada.
un método heredado firma (nombre, parámetros };
de la clase base. y tipo devuelto) en la clase Adaptación a necesidades
derivada, y luego realizar class ClaseDerivada : public específicas.
las modificaciones ClaseBase {
necesarias en la public: Añadir funcionalidad
implementación. void miMetodo() override { específica.
// Lógica adicional antes del
método heredado Polimorfismo con cambios
// ... adicionales

ClaseBase::miMetodo(); //
Llamada al método heredado

// Lógica adicional después


del método heredado
// ...
}
};
Actividades
1. EXPERIENCIA DE PRÁCTICA N° 01: CLASES ABSTRACTAS

#include <iostream>

class Animal {
public:
virtual void hacerSonido() const = 0;
};

class Perro : public Animal {


public:
void hacerSonido() const override {
std::cout << "El perro hace: ¡Guau guau!" << std::endl;
}
};

class Gato : public Animal {


public:
void hacerSonido() const override {
std::cout << "El gato hace: ¡Miau miau!" << std::endl;
}
};

class Vaca : public Animal {


public:
void hacerSonido() const override {
std::cout << "La vaca hace: ¡Muu muu!" << std::endl;
}
};

int main() {
Animal* perro = new Perro();
Animal* gato = new Gato();
Animal* vaca = new Vaca();

perro->hacerSonido();
gato->hacerSonido();
vaca->hacerSonido();
delete perro;
delete gato;
delete vaca;

return 0;
}

2. EXPERIENCIA DE PRÁCTICA N° 02: CLASES COMPLETAMENTE ABSTRACTAS

#include <iostream>
class Animal {
public:
virtual void hacerSonido() const = 0;
virtual ~Animal() {} // Agregamos un destructor virtual para la clase base
};

class Perro : public Animal {


public:
void hacerSonido() const override {
std::cout << "El perro hace: ¡Guau guau!" << std::endl;
}
};

class Gato : public Animal {


public:
void hacerSonido() const override {
std::cout << "El gato hace: ¡Miau miau!" << std::endl;
}
};

class Vaca : public Animal {


public:
void hacerSonido() const override {
std::cout << "La vaca hace: ¡Muu muu!" << std::endl;
}
};

int main() {
Animal* perro = new Perro();
Animal* gato = new Gato();
Animal* vaca = new Vaca();
perro->hacerSonido();
gato->hacerSonido();
vaca->hacerSonido();

delete perro;
delete gato;
delete vaca;

return 0;
}

3. EXPERIENCIA DE PRÁCTICA N° 03: MÉTODOS VIRTUALES

#include <iostream>

class Animal {
public:
virtual void hacerSonido() const = 0;
};

class Perro : public Animal {


public:
void hacerSonido() const override {
std::cout << "El perro hace: ¡Guau guau!" << std::endl;
}
};

class Gato : public Animal {


public:
void hacerSonido() const override {
std::cout << "El gato hace: ¡Miau miau!" << std::endl;
}
};

class Vaca : public Animal {


public:
void hacerSonido() const override {
std::cout << "La vaca hace: ¡Muu muu!" << std::endl;
}
};

int main() {
Animal* perro = new Perro();
Animal* gato = new Gato();
Animal* vaca = new Vaca();
perro->hacerSonido();
gato->hacerSonido();
vaca->hacerSonido();

delete perro;
delete gato;
delete vaca;

return 0;
}

4. EXPERIENCIA DE PRÁCTICA N° 04: REMPLAZO Y REFINAMIENTO

#include <iostream>

class Vehículo {
public:
virtual void acelerar() const {
std::cout << "Acelerando el vehículo." << std::endl;
}
};
class Coche : public Vehículo {
public:
void acelerar() const override {
std::cout << "Acelerando el coche." << std::endl;
}

void encenderLuces() const {


std::cout << "Luces del coche encendidas." << std::endl;
}
};

class Motocicleta : public Vehículo {


public:
void acelerar() const override {
std::cout << "Acelerando la motocicleta." << std::endl;
}
};
int main() {
Coche coche;
coche.acelerar();
coche.encenderLuces();

Motocicleta motocicleta;
motocicleta.acelerar();

return 0;
}
Ejercicios
1. Ejercicio

#include <iostream>

class Figura {
public:
virtual void dibujar() const = 0;
virtual double calcularArea() const = 0;
};

class Circulo : public Figura {


private:
double radio;
public:
Circulo(double r) : radio(r) {}

void dibujar() const override {


std::cout << "Dibujando un círculo." << std::endl;
}

double calcularArea() const override {


return 3.14159 * radio * radio;
}
};

class Rectangulo : public Figura {


private:
double base;
double altura;
public:
Rectangulo(double b, double h) : base(b), altura(h) {}

void dibujar() const override {


std::cout << "Dibujando un rectángulo." << std::endl;
}

double calcularArea() const override {


return base * altura;
}
};

class Triangulo : public Figura {


private:
double base;
double altura;
public:
Triangulo(double b, double h) : base(b), altura(h) {}

void dibujar() const override {


std::cout << "Dibujando un triángulo." << std::endl;
}

double calcularArea() const override {


return 0.5 * base * altura;
}
};

int main() {
Circulo circulo(5.0);
Rectangulo rectangulo(4.0, 6.0);
Triangulo triangulo(3.0, 7.0);

circulo.dibujar();
std::cout << "Área del círculo: " << circulo.calcularArea() << std::endl;

rectangulo.dibujar();
std::cout << "Área del rectángulo: " << rectangulo.calcularArea() << std::endl;

triangulo.dibujar();
std::cout << "Área del triángulo: " << triangulo.calcularArea() << std::endl;

return 0;
}
2. Ejercicio

#include <iostream>

class Reproductor {
public:
virtual void reproducir() = 0;
virtual void pausar() = 0;
virtual void detener() = 0;
};

class ReproductorMP3 : public Reproductor {


public:
void reproducir() override {
std::cout << "Reproduciendo archivo de audio MP3." << std::endl;
}

void pausar() override {


std::cout << "Pausando reproducción de archivo de audio MP3." << std::endl;
}

void detener() override {


std::cout << "Deteniendo reproducción de archivo de audio MP3." << std::endl;
}
};
int main() {
ReproductorMP3 reproductor;

reproductor.reproducir();
reproductor.pausar();
reproductor.detener();

return 0;
}

3. Ejercicio

#include <iostream>

class Empleado {
public:
virtual double calcularSalario() const = 0;
};

class EmpleadoTiempoCompleto : public Empleado {


private:
double salarioBase;
double bono;

public:
EmpleadoTiempoCompleto(double base, double b) : salarioBase(base), bono(b) {}

double calcularSalario() const override {


return salarioBase + bono;
}
};

class EmpleadoMedioTiempo : public Empleado {


private:
double salarioHora;
int horasTrabajadas;

public:
EmpleadoMedioTiempo(double hora, int horas) : salarioHora(hora),
horasTrabajadas(horas) {}

double calcularSalario() const override {


return salarioHora * horasTrabajadas;
}
};

int main() {
EmpleadoTiempoCompleto empleadoTiempoCompleto(2000.0, 500.0);
EmpleadoMedioTiempo empleadoMedioTiempo(15.0, 30);
std::cout << "Salario del empleado a tiempo completo: $" <<
empleadoTiempoCompleto.calcularSalario() << std::endl;
std::cout << "Salario del empleado a medio tiempo: $" <<
empleadoMedioTiempo.calcularSalario() << std::endl;

return 0;
}

Cuestionario
1. ¿Qué es una clase abstracta?

Una clase abstracta es una clase que no puede ser instanciada directamente, sino que se utiliza como una base para
otras clases derivadas. Puede contener métodos con implementaciones concretas, así como métodos abstractos que
deben ser implementados en las clases derivadas. Una clase abstracta proporciona una estructura común y establece
reglas y contratos para las clases hijas.

2. ¿Qué es una función virtual?

Una función virtual es una función que puede ser redefinida en las clases derivadas. Permite que el comportamiento
de la función sea específico para cada clase hija, incluso si se llama a través de un puntero o una referencia de la clase
base. Esto facilita el polimorfismo, donde un objeto puede mostrar comportamientos diferentes según el tipo de
objeto con el que se esté trabajando.

3. ¿Qué es una función virtual pura?

Una función virtual pura (también conocida como método virtual puro) es una función virtual que no tiene una
implementación en la clase base. Las clases que tienen una función virtual pura se convierten en clases abstractas y
deben ser implementadas en las clases derivadas. Estas funciones actúan como contratos obligatorios que deben
cumplir las clases hijas.

4. ¿Qué función cumplen las clases abstractas en las jerarquías de clases?

Las clases abstractas juegan un papel fundamental en las jerarquías de clases al proporcionar una base común para
las clases derivadas. Definen la estructura y los métodos que deben implementarse en las clases hijas, lo que garantiza
la coherencia y la consistencia en el diseño de la jerarquía. Además, permiten el polimorfismo al permitir el uso de
punteros y referencias de la clase base para manipular objetos de las clases derivadas.

5. ¿Por qué se pueden crear punteros a objetos de clases abstractas?

Se pueden crear punteros a objetos de clases abstractas porque los punteros no están vinculados a una
implementación concreta. Los punteros a una clase abstracta se utilizan para acceder a objetos de clases derivadas y
permiten manipularlos a través de la clase base, lo que facilita el polimorfismo y la escritura de código más genérico.

6. ¿Por qué se pueden crear referencias a objetos de clases abstractas?

Las referencias a objetos de clases abstractas también son posibles porque proporcionan un nivel de indirección similar
a los punteros. Las referencias permiten manipular objetos de clases derivadas a través de la clase base de manera
transparente, lo que facilita la implementación de polimorfismo y la escritura de código más claro y legible.

7. ¿Por qué se debe separar la interfaz de la implementación?

Se debe separar la interfaz de la implementación para promover la encapsulación y el ocultamiento de información.


La interfaz define los métodos y las reglas de interacción con el objeto, mientras que la implementación se refiere a la
forma en que se realizan las operaciones internamente. Separarlos permite cambios en la implementación sin afectar
el código que utiliza la interfaz, lo que mejora la modularidad, el mantenimiento y la reutilización del código.

8. ¿Qué es una clase completamente abstracta?

Una clase completamente abstracta es una clase que solo contiene métodos abstractos (funciones virtuales puras) y
no tiene implementaciones concretas. Estas clases solo se utilizan como bases para otras clases y no se pueden
instanciar directamente. Su propósito principal es proporcionar una estructura común y establecer contratos para las
clases derivadas.

9. ¿Qué es una interface?

Una interfaz es una colección de métodos abstractos que definen un conjunto de comportamientos que una clase
debe implementar. Las interfaces establecen un contrato que las clases deben cumplir y permiten una programación
orientada a interfaces. Proporcionan una forma de lograr la herencia múltiple y permiten una mayor flexibilidad y
reutilización del código al separar la definición de la implementación.

10. ¿Cuándo se debe usar una interface?

Se debe usar una interfaz cuando se necesita definir un conjunto común de métodos que deben implementar varias
clases independientes entre sí, pero que comparten un comportamiento similar. Las interfaces permiten que
diferentes clases cumplan un contrato común y facilitan la intercambiabilidad y el polimorfismo.

11. ¿Cómo se implementa una interface?

Una interfaz se implementa en una clase mediante la declaración de la implementación de cada uno de los métodos
definidos en la interfaz. La clase debe proporcionar una implementación concreta para cada método declarado en la
interfaz. Esto asegura que la clase cumpla con el contrato establecido por la interfaz.

12. ¿Cómo se beneficia el polimorfismo con las interfaces?

El polimorfismo se beneficia con las interfaces al permitir que diferentes objetos que implementan la misma interfaz
sean tratados de manera uniforme. Esto significa que se puede llamar a los métodos de la interfaz en objetos de
diferentes clases, siempre que implementen esa interfaz. Esto proporciona una mayor flexibilidad y reutilización del
código, ya que se pueden utilizar objetos intercambiables sin preocuparse por su tipo concreto.

13. ¿Cómo se beneficia la herencia con las interfaces?

La herencia se beneficia con las interfaces al permitir que una clase implemente múltiples interfaces. Esto facilita la
reutilización de código al permitir que una clase herede funcionalidades de varias fuentes a través de la
implementación de diferentes interfaces. Esto promueve la modularidad y la flexibilidad en el diseño de clases y
jerarquías de herencia.

14. ¿Qué es una clase proxy?

Una clase proxy es una clase que actúa como intermediario o representante de otra clase. Proporciona una interfaz
similar a la clase que está representando y puede agregar funcionalidad adicional, como control de acceso, registro o
implementación perezosa. Los objetos de la clase proxy se utilizan como sustitutos de los objetos originales y controlan
el acceso a ellos.

15. ¿En qué se diferencian las interfaces de las clases proxy?

Las interfaces definen un contrato que una clase debe cumplir, especificando los métodos que deben ser
implementados. Por otro lado, las clases proxy son objetos que actúan como intermediarios y proporcionan una
interfaz similar a la clase que representan, pero pueden agregar funcionalidad adicional. Mientras que una interfaz se
enfoca en la definición de comportamiento, las clases proxy se centran en el control y la manipulación de los objetos
representados.

16. ¿Cuándo se debe usar un método virtual?

Se debe usar un método virtual cuando se desea permitir que las clases derivadas redefinan su comportamiento. Esto
facilita la personalización y la adaptación de los métodos en las clases hijas según sus necesidades específicas. Los
métodos virtuales proporcionan una forma de lograr el polimorfismo y permiten escribir código más genérico y
flexible.

17. ¿Cómo se invoca un método virtual?

Un método virtual se invoca utilizando un puntero o una referencia a la clase base que apunta a un objeto de la clase
derivada. Esto permite que se ejecute la implementación del método correspondiente a la clase derivada en lugar de
la implementación de la clase base. La llamada se resuelve en tiempo de ejecución, lo que permite que el polimorfismo
y el comportamiento dinámico se apliquen adecuadamente.

18. ¿Cómo se invoca un método virtual en una jerarquía de clases?

Para invocar un método virtual en una jerarquía de clases, se utiliza la sintaxis de puntero o referencia a la clase base.
Si el método es virtual y ha sido redefinido en una clase derivada, la implementación correspondiente de la clase
derivada se ejecutará en tiempo de ejecución. Esto permite que el comportamiento polimórfico se aplique incluso
cuando se trabaja con punteros o referencias de la clase base.

19. ¿Qué es una Tabla de funciones virtuales?

Una Tabla de funciones virtuales (también conocida como tabla de métodos virtuales o tabla de dispatch) es una
estructura de datos utilizada para resolver en tiempo de ejecución qué implementación de un método virtual debe
invocarse en una jerarquía de clases. Cada clase que contiene al menos un método virtual tiene su propia tabla de
funciones virtuales que almacena punteros a las implementaciones de los métodos virtuales en esa clase.

20. ¿Cuál es la diferencia entre un método virtual y un método virtual puro?

La diferencia entre un método virtual y un método virtual puro (función virtual pura) radica en su implementación en
la clase base. Un método virtual tiene una implementación concreta en la clase base, lo que permite llamarlo
directamente. Por otro lado, un método virtual puro no tiene implementación en la clase base y debe ser
implementado en las clases derivadas. Esto hace que la clase base se convierta en una clase abstracta y no pueda ser
instanciada directamente.

21. ¿En qué consiste el reemplazo?

El reemplazo consiste en sustituir o modificar el comportamiento de un método en una clase derivada. Esto se logra
al redefinir el método virtual en la clase hija, proporcionando una nueva implementación que reemplaza la
implementación heredada de la clase base. El reemplazo permite personalizar el comportamiento de los métodos en
las clases derivadas sin afectar la funcionalidad de la clase base.

22. ¿En qué consiste el refinamiento?

El refinamiento consiste en mejorar o extender la funcionalidad de un método en una clase derivada. Esto se logra al
redefinir el método virtual en la clase hija y agregar funcionalidad adicional a la implementación existente en la clase
base. El refinamiento permite enriquecer el comportamiento de los métodos heredados y adaptarlos a las necesidades
específicas de la clase derivada.

23. ¿Qué ventajas trae la aplicación del reemplazo?


La aplicación del reemplazo ofrece ventajas en términos de adaptabilidad y personalización. Permite que las clases
derivadas modifiquen y extiendan el comportamiento heredado de la clase base, lo que proporciona flexibilidad en el
diseño y la implementación de sistemas. El reemplazo también facilita la reutilización de código, ya que permite que
las clases derivadas compartan una estructura común mientras adaptan y mejoran comportamientos específicos.

24. ¿Qué sucede si los para metros formales difieren entre los métodos de las clases de la

jerarquía?

Si los parámetros formales difieren entre los métodos de las clases de la jerarquía, se produce una incompatibilidad y
la llamada al método puede ser ambigua o incorrecta. Para evitar esto, es importante asegurarse de que los métodos
en la jerarquía de clases tengan una firma consistente, es decir, que tengan los mismos tipos de parámetros y el mismo
tipo de valor de retorno. Esto garantiza que se pueda llamar al método adecuado según el tipo de objeto con el que
se esté trabajando.

25. ¿Qué es la signature o firma del método?

La signature o firma del método se refiere a la combinación de su nombre, tipo de parámetros y tipo de valor de
retorno. La firma de un método es única dentro de una clase y se utiliza para identificar y resolver llamadas a métodos
en tiempo de compilación. La signature del método es parte de su interfaz y define cómo se llama y qué tipo de valores

Conclusiones
1. Los conceptos de Clases Abstractas e Interfaces son fundamentales en la POO para establecer una base común y
definir contratos entre las clases derivadas. Estos conceptos promueven la modularidad y la reutilización de código al
proporcionar una estructura y un conjunto de métodos que deben implementarse.

2. Las Funciones Virtuales permiten la redefinición de comportamientos en las clases derivadas, lo que posibilita el
polimorfismo y la escritura de código más flexible y genérico. Esto facilita la adaptación del comportamiento de los
objetos según el contexto en el que se utilicen.

3. El Remplazo y Refinamiento son conceptos que contribuyen a mantener la coherencia y flexibilidad en la evolución
de los sistemas. Permiten reemplazar o mejorar comportamientos en las clases derivadas sin afectar la estructura o el
funcionamiento de las clases base, lo que resulta en un código más adaptable y escalable.

4. A través de ejemplos prácticos y el estudio de diferentes lenguajes de programación orientados a objetos como C++,
Java, Python y JavaScript, se demuestra cómo estos conceptos se aplican en la práctica y ayudan a resolver problemas
del mundo real. Además, se destaca la importancia de escribir código modular, reutilizable y mantenible para facilitar
el desarrollo y la evolución de los sistemas.

También podría gustarte