Está en la página 1de 34

Instituto Politécnico Nacional.

Escuela Superior de Ingeniería Mecánica y Eléctrica.

Ingeniería en Comunicaciones y Electrónica.

Unidad Culhuacán.

Programación Orientada a Objetos.

Tarea 2: Polimorfismo.

Profesor: García Cabello Víctor.

Alumno: Perez Gallegos Israel Alejandro

Grupo: 2EV35
Definición de Polimorfismo.
El polimorfismo es un concepto utilizado en diversos campos, como la
programación, la biología y la química, pero a menudo se asocia con
la programación orientada a objetos. A continuación, te proporcionaré
la definición específica de polimorfismo en el contexto de la
programación orientada a objetos:
En programación orientada a objetos, el polimorfismo se refiere a la
capacidad de un objeto para presentar distintas interfaces o
comportamientos dependiendo del contexto en el que se utilice. Esto
permite que objetos de diferentes clases sean tratados de manera
uniforme a través de una interfaz común.
Existen dos tipos principales de polimorfismo:
Polimorfismo de tiempo de compilación (Compile-time
Polymorphism): También conocido como sobrecarga de operadores
o funciones, ocurre durante la compilación. Se trata de la capacidad de
una función u operador para realizar diferentes acciones según el
número o tipo de parámetros.
Polimorfismo de tiempo de ejecución (Runtime Polymorphism):
También conocido como polimorfismo de subtipo, ocurre durante la
ejecución del programa. Se logra a través de la herencia y el uso de
funciones virtuales. En este caso, un objeto puede comportarse de
manera diferente según su tipo derivado cuando se utiliza a través de
un puntero o una referencia de la clase base.
El polimorfismo facilita el diseño de software más flexible y extensible,
ya que permite que distintas clases compartan una interfaz común y
puedan ser tratadas de manera uniforme, lo que facilita la creación de
código más genérico y reutilizable.
Clases Abstractas.
Las clases abstractas son un concepto en programación orientada a
objetos (POO) que se utiliza para proporcionar una base común para
un conjunto de clases relacionadas. Una clase abstracta no puede ser
instanciada por sí misma, pero puede contener métodos abstractos,
los cuales son métodos que solo tienen una firma (nombre,
parámetros y tipo de retorno), pero no tienen una implementación
concreta. Estos métodos abstractos deben ser implementados por las
clases derivadas que heredan de la clase abstracta.
En resumen, las clases abstractas sirven como plantillas para otras
clases y proporcionan una interfaz común a través de la cual las
clases derivadas pueden heredar y compartir comportamientos.
Además de los métodos abstractos, una clase abstracta también
puede contener métodos concretos (métodos con implementación) y
atributos.
En muchos lenguajes de programación orientados a objetos, como
Java o C#, se utiliza la palabra clave "abstract" para definir una clase
abstracta y la palabra clave "abstract" para definir métodos abstractos
dentro de esas clases. Aquí un ejemplo:
abstract class Figura
{
// Atributos y/o métodos concretos
// Método abstracto que debe ser implementado por las clases
derivadas
abstract void dibujar();
}
class Circulo extends Figura
{
// Implementación del método abstracto
void dibujar()
{
// Código para dibujar un círculo
}
}
class Cuadrado extends Figura
{
// Implementación del método abstracto
void dibujar()
{
// Código para dibujar un cuadrado
}
}
En este ejemplo, “Figura” es una clase abstracta con un método
abstracto llamado “dibujar()”. Las clases “Circulo” y “Cuadrado” son
clases que heredan de la clase “Figura” y deben proporcionar una
implementación concreta para el método “dibujar()”.
Métodos Abstractos.
Un método abstracto es un tipo de método en la programación
orientada a objetos que no tiene una implementación en la clase en la
que se declara. En lugar de proporcionar un cuerpo de código
concreto, un método abstracto solo define la firma del método,
especificando el nombre del método, su tipo de retorno y los tipos de
sus parámetros.
En muchos lenguajes de programación, como Java o C#, se utiliza la
palabra clave "abstract" para declarar un método abstracto. Las clases
que contienen métodos abstractos deben ser marcadas como
abstractas también. Las clases derivadas de una clase abstracta
deben proporcionar implementaciones concretas para todos los
métodos abstractos heredados.
El propósito de los métodos abstractos es proporcionar una estructura
básica en una clase base, mientras que las clases derivadas pueden
proporcionar implementaciones específicas según sea necesario. Esto
facilita la creación de una jerarquía de clases y permite la
implementación de polimorfismo, ya que las instancias de las clases
derivadas pueden tratarse como instancias de la clase base.
Implementación de Clases Abstractas.
Puedes usar clases abstractas para definir interfaces y proporcionar
una base común para clases derivadas. Para crear una clase
abstracta, debes tener al menos una función virtual pura. Aquí hay un
ejemplo básico de cómo implementar clases abstractas en C++:
#include <iostream>
// Clase abstracta
class Forma
{
public:
// Función virtual pura para calcular el área
virtual double calcularArea() const = 0;
// Función normal
void mostrarInformacion() const
{
std::cout << "Esta es una forma." << std::endl;
}
// Destructor virtual para asegurar la llamada a los destructores de las
clases derivadas
virtual ~Forma()
{}
};
// Clase derivada: Rectángulo
class Rectangulo : public Forma
{
private:
double ancho;
double alto;
public:
Rectangulo(double ancho, double alto) : ancho(ancho), alto(alto)
{}
// Implementación de la función virtual pura
double calcularArea() const override
{
return ancho * alto;
}
};
// Clase derivada: Círculo
class Circulo : public Forma {
private:
double radio;
public:
Circulo(double radio) : radio(radio)
{}
// Implementación de la función virtual pura
double calcularArea() const override
{
return 3.14159 * radio * radio;
}
};
int main()
{
// Crear objetos de las clases derivadas
Rectangulo rectangulo(5.0, 3.0);
Circulo circulo(2.5);
// Acceder a las funciones de la clase base y derivada
rectangulo.mostrarInformacion();
std::cout << "Área del rectángulo: " << rectangulo.calcularArea() <<
std::endl;
circulo.mostrarInformacion();
std::cout << "Área del círculo: " << circulo.calcularArea() <<
std::endl;
return 0;
}
En este ejemplo, la clase “Forma” es una clase abstracta con una
función virtual pura llamada “calcularArea()”. Las clases derivadas
(“Rectangulo” y “Circulo”) deben implementar esta función para poder
ser instanciadas. Además, la función “mostrarInformacion()” es una
función común para todas las formas.
En una clase abstracta no puede ser instanciada directamente; solo se
pueden crear instancias de clases derivadas que implementen todas
las funciones virtuales puras de la clase abstracta.
Modelado de C.A.
El modelado de circuitos de corriente alterna (C.A.) en programación
orientada a objetos (POO) implica la representación de componentes
eléctricos y la interacción entre ellos mediante el uso de clases y
objetos.
#include <iostream>
#include <complex>
// Clase base para componentes de circuito
class Componente
{
public:
virtual std::complex<double> obtenerImpedancia() const = 0;
};
// Clase para representar resistencias
class Resistencia : public Componente
{
private:
double resistencia;
public:
Resistencia(double resistencia) : resistencia(resistencia)
{}
std::complex<double> obtenerImpedancia() const override
{
return resistencia;
}
};
// Clase para representar inductancias
class Inductancia : public Componente
{
private:
double inductancia;
public:
Inductancia(double inductancia) : inductancia(inductancia)
{}
std::complex<double> obtenerImpedancia() const override
{
return std::complex<double>(0.0, 2 * M_PI * 60 * inductancia);
// Frecuencia de 60 Hz
}
};
// Clase para representar un circuito que contiene componentes
class Circuito
{
private:
Componente* componente1;
Componente* componente2;
public:
Circuito(Componente* comp1, Componente* comp2) :
componente1(comp1), componente2(comp2)
{}
std::complex<double> calcularImpedanciaTotal() const
{
return componente1->obtenerImpedancia() + componente2-
>obtenerImpedancia();
}
};
int main()
{
// Crear resistencia de 10 ohmios
Resistencia resistor(10.0);
// Crear inductancia de 0.1 henrios
Inductancia inductor(0.1);
// Crear un circuito con la resistencia y la inductancia
Circuito circuito(&resistor, &inductor);
// Calcular la impedancia total del circuito
std::complex<double> impedanciaTotal =
circuito.calcularImpedanciaTotal();
// Mostrar el resultado
std::cout << "Impedancia total del circuito: " << impedanciaTotal << "
ohmios" << std::endl;
return 0;
}
En este ejemplo, las clases “Resistencia” e “Inductancia” heredan de la
clase base abstracta “Componente”. Cada una de estas clases
implementa la función virtual “obtenerImpedancia()”. La clase “Circuito”
tiene dos miembros que son punteros a objetos de tipo “Componente”,
y su función “calcularImpedanciaTotal()” suma las impedancias de
estos componentes.
Interfaces.
En el contexto de la programación orientada a objetos (POO), una
interfaz es un conjunto de métodos abstractos que define un
comportamiento común para clases que la implementan. Las
interfaces proporcionan un medio para especificar un contrato que las
clases derivadas deben seguir, pero no contienen implementaciones
concretas de los métodos. En lugar de eso, las clases que
implementan una interfaz deben proporcionar sus propias
implementaciones para los métodos definidos por la interfaz.
Las interfaces se definen con la palabra clave “interface”. Aquí hay un
ejemplo:
// Definición de una interfaz en C#
interface IImprimible
{
void Imprimir(); // Método abstracto (sin implementación)
}
// Clase que implementa la interfaz
class Impresora : IImprimible
{
public void Imprimir()
{
Console.WriteLine("Imprimiendo...");
}
}
En este ejemplo, la clase “Imprimible” hereda de “ABC” (Abstract Base
Class) y utiliza el decorador “@abstractmethod” para definir un método
abstracto “imprimir”. La clase “Impresora” luego hereda de “Imprimible”
y proporciona una implementación concreta para el método “imprimir”.
La implementación exacta de interfaces puede variar entre lenguajes
de programación, pero el concepto general es proporcionar una forma
de definir un contrato común para las clases.
Implementacion de interfaces.
La implementación de interfaces en programación orientada a objetos
(POO) puede variar según el lenguaje de programación que estés
utilizando.
// Definición de la interfaz
interface IImprimible
{
void Imprimir();
}
// Clase que implementa la interfaz
class Impresora : IImprimible
{
public void Imprimir()
{
Console.WriteLine("Imprimiendo...");
}
}

// Uso de la clase
class Program
{
static void Main(string[] args)
{
Impresora impresora = new Impresora();
impresora.Imprimir();
}
}
Estos ejemplos muestran cómo definir una interfaz y cómo
implementarla en una clase concreta. En cada lenguaje, se crea una
interfaz con un método (o más) abstracto, y luego se proporciona una
implementación concreta en una clase que implementa esa interfaz.
Recuerda que, dependiendo del lenguaje de programación, la sintaxis
y la semántica pueden variar, pero el concepto general de una interfaz
y su implementación es común en muchos lenguajes orientados a
objetos.
Herencia de Interfaces.
La herencia de interfaces es un concepto importante en programación
orientada a objetos (POO) que permite que una interfaz herede las
declaraciones de otra interfaz. Esto permite construir jerarquías de
interfaces que pueden compartir un conjunto común de métodos. Aquí
un ejemplo:
// Interfaz base
interface IImprimible
{
void Imprimir();
}
// Interfaz derivada que hereda de la interfaz base
interface IImprimibleAvanzado : IImprimible
{
void ImprimirDetalles();
}
// Clase que implementa la interfaz derivada
class ImpresoraAvanzada : IImprimibleAvanzado
{
public void Imprimir()
{
Console.WriteLine("Imprimiendo...");
}
public void ImprimirDetalles()
{
Console.WriteLine("Imprimiendo detalles...");
}
}
// Uso de la clase
class Program
{
static void Main(string[] args)
{
ImpresoraAvanzada impresora = new ImpresoraAvanzada();
impresora.Imprimir();
impresora.ImprimirDetalles();
}
}
En estos ejemplos, las interfaces derivadas “(ImprimibleAvanzado” e
“IImprimibleAvanzado”) heredan de las interfaces bases (“Imprimible” e
“IImprimible”). Las clases concretas (“ImpresoraAvanzada” e
“ImpresoraAvanzada” en este caso) implementan las interfaces
derivadas y, por lo tanto, deben proporcionar implementaciones para
todos los métodos en las interfaces base y derivada.
La herencia de interfaces proporciona una forma de organizar y
compartir comportamientos comunes en una jerarquía de interfaces.
Cada interfaz puede extender la funcionalidad de la interfaz base y
agregar nuevos métodos.
Variables polimórficas.
En programación orientada a objetos (POO), el término "polimorfismo"
se refiere a la capacidad de objetos de diferentes clases de responder
a un mismo mensaje o función de manera diferente. Las variables
polimórficas son variables que pueden hacer referencia a objetos de
diferentes tipos y, por lo tanto, pueden tomar diferentes formas durante
la ejecución del programa.
Hay dos formas principales de polimorfismo en POO: el polimorfismo
de tiempo de compilación (también conocido como polimorfismo
estático o polimorfismo de compilación) y el polimorfismo de tiempo de
ejecución (también conocido como polimorfismo dinámico o
polimorfismo de ejecución). Ambas formas implican el uso de variables
polimórficas.
1. Polimorfismo de Tiempo de Compilación:
En este caso, el polimorfismo se resuelve en tiempo de compilación y
está asociado con el uso de sobrecarga de funciones y operadores. Es
decir, el compilador decide qué versión de la función u operador
utilizar en función de los tipos de datos de las variables en tiempo de
compilación.
#include <iostream>
// Ejemplo de polimorfismo de tiempo de compilación
int sumar(int a, int b)
{
return a + b;
}
double sumar(double a, double b)
{
return a + b;
}
int main()
{
int resultado1 = sumar(3, 4);
double resultado2 = sumar(2.5, 3.7);
std::cout << "Resultado 1: " << resultado1 << std::endl;
std::cout << "Resultado 2: " << resultado2 << std::endl;
return 0;
}
2. Polimorfismo de Tiempo de Ejecucion.
En este caso, el polimorfismo se resuelve en tiempo de ejecución y
está asociado con el uso de clases, herencia y funciones virtuales. Las
variables polimórficas se logran mediante el uso de punteros o
referencias a la clase base.
#include <iostream>
// Clase base abstracta
class Figura
{
public:
virtual void dibujar() const = 0; // Función virtual pura
};
// Clase derivada
class Circulo : public Figura
{
public:
void dibujar() const override
{
std::cout << "Dibujando un círculo." << std::endl;
}
};
// Clase derivada
class Cuadrado : public Figura
{
public:
void dibujar() const override
{
std::cout << "Dibujando un cuadrado." << std::endl;
}
};
int main()
{
Figura* figura1 = new Circulo();
Figura* figura2 = new Cuadrado();
figura1->dibujar(); // Polimorfismo en tiempo de ejecución
figura2->dibujar();
delete figura1;
delete figura2;
return 0;
}
En este ejemplo, las clases “Circulo” y “Cuadrado” heredan de la clase
base “Figura”. Las funciones virtuales permiten que las funciones sean
redefinidas por las clases derivadas. Las variables polimórficas, en
este caso, son punteros a la clase base que apuntan a objetos de las
clases derivadas. El polimorfismo se manifiesta en tiempo de ejecución
cuando se llama a la función “dibujar” a través de las variables
polimórficas.
Uso y Aplicaciones de las Variables Polimorficas.
Las variables polimórficas y el polimorfismo en general son conceptos
fundamentales en programación orientada a objetos (POO) y ofrecen
varias ventajas en términos de flexibilidad, reutilización de código y
diseño modular. Aquí hay algunas aplicaciones y usos comunes de
variables polimórficas:
1. Diseño de Interfaces Comunes:
Las variables polimórficas permiten diseñar interfaces comunes para
clases que comparten comportamientos similares.
Esto facilita la creación de código que pueda trabajar con múltiples
tipos de objetos sin preocuparse por sus implementaciones concretas.
2. Polimorfismo de Tiempo de Ejecución:
Permite utilizar punteros o referencias a la clase base para referenciar
objetos de clases derivadas.
Facilita la implementación de sistemas donde el comportamiento
específico se determina en tiempo de ejecución.
3. Herencia y Reutilización de Código:
Las variables polimórficas son útiles cuando se utiliza herencia para
crear clases derivadas que comparten una interfaz común.
Permite la reutilización del código al utilizar métodos de la clase base
a través de referencias o punteros a la clase base.
4. Desarrollo de Marcos (Frameworks):
En el desarrollo de frameworks, las variables polimórficas permiten a
los usuarios extender y personalizar el comportamiento del framework
al proporcionar sus propias implementaciones de clases base.
5. Aplicaciones Gráficas y de Interfaz de Usuario:
En entornos gráficos, las variables polimórficas son utilizadas para
representar elementos gráficos como botones, ventanas, y otros
controles.
Permite tratar distintos tipos de controles de manera uniforme.
6. Polimorfismo en Algoritmos:
Permite escribir algoritmos que operan sobre tipos de datos genéricos
sin preocuparse por los detalles específicos de implementación.
Promueve la creación de algoritmos más genéricos y flexibles.
7. Implementación de Interfaces Gráficas y Manejo de Eventos:
En sistemas con interfaces gráficas, las variables polimórficas se
utilizan para manejar eventos de manera genérica,
independientemente del tipo de control o elemento gráfico.
8. Sistemas de Plug-ins:
Facilita la creación de sistemas extensibles donde nuevos módulos o
funcionalidades pueden ser añadidos sin modificar el código existente.
9. Manejo de Colecciones de Objetos:
Permite almacenar objetos de diferentes tipos en una misma colección
(como un array o lista) mediante el uso de punteros o referencias a la
clase base.
10. Implementación de Polimorfismo Paramétrico:
En lenguajes que soportan polimorfismo paramétrico, como C++ con
plantillas (templates), se pueden utilizar variables polimórficas con
tipos genéricos.
El uso de variables polimórficas contribuye a la creación de código
más flexible, mantenible y extensible, permitiendo adaptarse a
cambios en los requisitos del software de manera más eficiente.
Reutilizacion del código.
La reutilización del código es uno de los principios fundamentales en
programación orientada a objetos (POO), y el polimorfismo juega un
papel importante en facilitar esta reutilización. La reutilización del
código implica escribir código de manera que pueda ser utilizado
nuevamente en diferentes contextos y situaciones. Aquí te explico
cómo el polimorfismo contribuye a la reutilización del código en el
contexto de la POO:

1. Interfaz Común:
El polimorfismo permite definir interfaces comunes (a través de clases
base o interfaces) que especifican un conjunto de métodos que deben
ser implementados por las clases derivadas.
Las clases derivadas pueden proporcionar implementaciones
específicas, pero las invocaciones a través de la interfaz común
permiten tratar diferentes clases de manera uniforme.
2. Herencia:
La herencia, que es un concepto clave en la POO, permite que una
clase (clase derivada) herede características y comportamientos de
otra clase (clase base).
El polimorfismo permite utilizar la interfaz de la clase base para
referenciar objetos de la clase derivada, lo que facilita la reutilización
del código al tratar objetos derivados de manera genérica.
3. Polimorfismo de Tiempo de Ejecución:
El polimorfismo de tiempo de ejecución permite que un mismo código
pueda operar sobre diferentes tipos de objetos durante la ejecución del
programa.
Las variables polimórficas (punteros o referencias a la clase base)
permiten invocar métodos específicos de la clase derivada sin conocer
la implementación concreta en tiempo de compilación.
4. Algoritmos Genéricos:
El polimorfismo facilita la creación de algoritmos genéricos que pueden
operar sobre diferentes tipos de datos sin conocer los detalles de
implementación.
Esto promueve la reutilización del código al escribir algoritmos una vez
y utilizarlos con distintos tipos de datos.
5. Interfaces en Aplicaciones Gráficas:
En aplicaciones gráficas, las interfaces comunes para elementos
gráficos (botones, ventanas, etc.) permiten tratarlos de manera
uniforme en el código.
Los elementos gráficos pueden ser personalizados y extendidos
mediante la creación de nuevas clases derivadas sin modificar el
código existente.
6. Sistemas Extensibles:
El polimorfismo es esencial para la creación de sistemas extensibles,
donde nuevos módulos o funcionalidades pueden ser agregados sin
afectar el código existente.
Permite la creación de arquitecturas de software que puedan
evolucionar y adaptarse a cambios de manera más fácil.
7. Manejo de Colecciones Genéricas:
Las colecciones de objetos polimórficos permiten almacenar y
manipular objetos de diferentes tipos a través de la interfaz común.
8. Patrones de Diseño:
El polimorfismo es un concepto fundamental en la implementación de
patrones de diseño, como el patrón de estrategia, el patrón de
comando y otros, que promueven la reutilización del código.
La combinación de herencia, interfaces comunes y polimorfismo
proporciona una poderosa capacidad para reutilizar código en la POO.
Este enfoque permite escribir código más modular, mantenible y
flexible, ya que las clases pueden ser extendidas o modificadas sin
afectar otras partes del sistema.
Identificar clases que no requieran ser instanciadas, por su nivel
de abstracción.
En programación orientada a objetos, las clases que no requieren ser
instanciadas se conocen como "clases abstractas". Estas clases
suelen contener al menos un método abstracto (sin implementación)
que debe ser implementado por las clases derivadas. Las clases
abstractas proporcionan una abstracción de un concepto general y no
tienen una implementación completa en sí mismas.
1. Clase abstracta:
abstract class Vehiculo
{
abstract void arrancar();
abstract void detener();
}
Nivel de Abstracción: Alto. Esta clase es abstracta y proporciona
solo métodos abstractos. No debe ser instanciada directamente.
2. Clase concreta :
class Coche extends Vehiculo
{
void arrancar()
{
System.out.println("Arrancando el coche");
}
void detener()
{
System.out.println("Deteniendo el coche");
}
void conducir()
{
System.out.println("Conduciendo el coche");
}
}
Nivel de Abstracción: Medio. La clase Coche es concreta y puede
ser instanciada. Hereda de la clase abstracta Vehiculo.
3. Clase Interfaz:
interface Imprimible
{
void imprimir();
}
Nivel de Abstracción: Alto. Una interfaz define solo métodos
abstractos. No debe ser instanciada directamente.
4. Clase concreta que implementa la interfaz:
class Documento implements Imprimible
{
void imprimir()
{
System.out.println("Imprimiendo el documento");
}
void editar()
{
System.out.println("Editando el documento");
}
}
Nivel de Abstracción: Medio. La clase Documento es concreta y
puede ser instanciada. Implementa la interfaz Imprimible.
5. Clase Utilidad:
public class Calculadora
{
static double sumar(double a, double b)
{
return a + b;
}
static double restar(double a, double b)
{
return a - b;
}
}
Nivel de Abstracción: Bajo. La clase Calculadora es una clase
utilitaria con métodos estáticos. No debe ser instanciada.
Las clases que no requieren ser instanciadas directamente suelen ser
aquellas de nivel alto de abstracción, como clases abstractas e
interfaces. Estas clases proporcionan una base común para las clases
concretas que las implementan. Las clases de nivel medio pueden ser
instanciadas y proporcionan una implementación más específica. Las
clases de nivel bajo, como clases utilitarias, suelen tener métodos
estáticos y no se instancian directamente.
Implementacion de clases abstractas
// Clase abstracta Figura
abstract class Figura
{
abstract double calcularArea(); // Método abstracto para calcular el
área
abstract void dibujar(); // Método abstracto para dibujar la figura
}
// Clase concreta Circulo que extiende de Figura
class Circulo extends Figura
{
private double radio;
Circulo(double radio)
{
this.radio = radio;
}
double calcularArea()
{
return Math.PI * radio * radio;
}
void dibujar()
{
System.out.println("Dibujando un círculo");
}
}
// Clase concreta Rectangulo que extiende de Figura
class Rectangulo extends Figura
{
private double base;
private double altura;
Rectangulo(double base, double altura)
{
this.base = base;
this.altura = altura;
}
double calcularArea()
{
return base * altura;
}
void dibujar()
{
System.out.println("Dibujando un rectángulo");
}
}
// Clase principal para probar la implementación
public class Main
{
public static void main(String[] args)
{
// Crear instancias de las clases concretas
Circulo circulo = new Circulo(5.0);
Rectangulo rectangulo = new Rectangulo(4.0, 6.0);
// Utilizar métodos de las clases concretas
circulo.dibujar();
System.out.println("Área del círculo: " + circulo.calcularArea());
rectangulo.dibujar();
System.out.println("Área del rectángulo: " + rectangulo.calcularArea());
}
}
En este ejemplo, la clase “Figura” es abstracta y contiene dos métodos
abstractos: “calcularArea” y “dibujar”. Las clases concretas “Circulo” y
“Rectangulo” extienden de “Figura” y proporcionan implementaciones
específicas para esos métodos abstractos.

Crear una aplicacion que incluya herencia de interfaces que


defina el comportamiento de las clases.
// Definición de la interfaz Animal
interface Animal
{
void hacerSonido();
void moverse();
}
// Implementación de la clase Perro que implementa la interfaz Animal
class Perro implements Animal
{
@Override
public void hacerSonido()
{
System.out.println("El perro ladra");
}
@Override
public void moverse()
{
System.out.println("El perro corre");
}
}
// Implementación de la clase Pajaro que implementa la interfaz Animal
class Pajaro implements Animal
{
@Override
public void hacerSonido()
{
System.out.println("El pájaro canta");
}
@Override
public void moverse()
{
System.out.println("El pájaro vuela");
}
}
// Clase principal para probar la implementación
public class AplicacionAnimales
{
public static void main(String[] args)
{
// Crear instancias de las clases Perro y Pajaro
Animal perro = new Perro();
Animal pajaro = new Pajaro();
// Utilizar métodos de las clases implementando la interfaz Animal
perro.hacerSonido();
perro.moverse();
pajaro.hacerSonido();
pajaro.moverse();
}
}
En este ejemplo, la interfaz “nimal” define el comportamiento común
que se espera de cualquier clase que represente un animal. Las
clases “Perro” y “Pajaro” implementan la interfaz “Animal” y
proporcionan sus propias implementaciones para los métodos
“hacerSonido” y “moverse”.

Al ejecutar la aplicación, verás que cada clase de animal tiene su


propio comportamiento específico, pero ambas comparten la interfaz
común definida por la interfaz “Animal”. Esto ilustra el concepto de
herencia de interfaces en la programación orientada a objetos.

Crear una aplicación que declare variables miembros de una


clase abstracta o interfaz que demuestre el polimorfismo al
cambiar el comportamiento de un objeto.
// Interfaz Forma
interface Forma
{
double calcularArea();
}
// Clase abstracta Figura que implementa la interfaz Forma
abstract class Figura implements Forma
{
// Variable miembro de la clase abstracta
protected String nombre;
// Constructor de la clase abstracta
public Figura(String nombre)
{
this.nombre = nombre;
}
// Método abstracto
abstract void dibujar();
}
// Clase concreta Circulo que extiende de Figura
class Circulo extends Figura
{
private double radio;
public Circulo(String nombre, double radio)
{
super(nombre);
this.radio = radio;
}
@Override
public double calcularArea()
{
return Math.PI * radio * radio;
}
@Override
void dibujar()
{
System.out.println("Dibujando un círculo");
}
}
// Clase concreta Rectangulo que extiende de Figura
class Rectangulo extends Figura
{
private double base;
private double altura;
public Rectangulo(String nombre, double base, double altura)
{
super(nombre);
this.base = base;
this.altura = altura;
}
@Override
public double calcularArea()
{
return base * altura;
}
@Override
void dibujar()
{
System.out.println("Dibujando un rectángulo");
}
}
// Clase CalculadoraDeAreas que demuestra el polimorfismo
class CalculadoraDeAreas
{
// Método que acepta objetos de tipo Forma
public static void imprimirArea(Forma forma)
{
System.out.println("Área de " +
forma.getClass().getSimpleName() + ": " + forma.calcularArea());
}
}
// Clase principal para probar la implementación
public class AplicacionPolimorfismo
{
public static void main(String[] args)
{
// Crear instancias de las clases Circulo y Rectangulo
Circulo circulo = new Circulo("MiCirculo", 5.0);
Rectangulo rectangulo = new Rectangulo("MiRectangulo", 4.0, 6.0);
// Utilizar el polimorfismo
CalculadoraDeAreas.imprimirArea(circulo);
CalculadoraDeAreas.imprimirArea(rectangulo);
}
}
En esta aplicación la clase “Figura” es una clase abstracta que
implementa la interfaz “Forma”. Se tiene una variable miembro llamada
“nombre” en la clase abstracta, y dos clases concretas (“Circulo” y
“Rectangulo”) que extienden de “Figura” y proporcionan
implementaciones concretas para los métodos “calcularArea” y
“dibujar”.

La clase “CalculadoraDeAreas” tiene un método llamado


“imprimirArea” que acepta objetos de tipo “Forma”. Esta clase
demuestra el polimorfismo, ya que puede aceptar instancias tanto de
“Circulo” como de “Rectangulo” y utilizar el método “calcularArea”
correspondiente a la implementación concreta de cada objeto.

Al ejecutar la aplicación, verás que el método “imprimirArea” puede


trabajar con instancias de diferentes clases concretas que
implementan la interfaz “Forma”, demostrando así el polimorfismo en
acción.

También podría gustarte