lunes, 26 de junio de 2017

Un Ejemplo de Polimorfismo en C++


La idea es mostrar un ejemplo de polimorfismo para los que comienzan a programar en el paradigma orientado a objetos.

La idea es que una empresa tiene un conjunto de bienes los cuales tienen un valor y a la vez algunos bienes pueden ser amortizados (La amortización es un término económico y contable, referido al proceso de distribución de gasto en el tiempo de un valor duradero. Adicionalmente se utiliza como sinónimo de depreciación en cualquiera de sus métodos.)

Los bienes se clasifican en inmuebles, muebles y rodados. A la vez los inmuebles no pierden el valor en el tiempo (es decir no son amortizables) . El software debe proveer una forma de saber el valor de todos los bienes y calcular su amortización.

Para resolver este problema vamos a definir 1 clase abstracta bien que describa la característica que tienen los bienes de saber su valor y la característica de calcular la amortización. A la vez vamos a crear un gestor contable que imprima las amortizaciones.

Veamos la clase abstracta bien:

bien.h :

#ifndef BIEN_H
#define BIEN_H

#include <iostream>

class Bien
{
protected:
    double valor = 0.0;
public:
    Bien();
    double virtual amortizar() = 0;

    void setValor(double valor);

    friend std::ostream& operator<<(std::ostream& os, const Bien& obj);
};

#endif // BIEN_H

bien.cpp : 

#include "bien.h"

Bien::Bien()
{
    this->valor = 0;
}

void Bien::setValor(double valor){
    this->valor = valor;
}

std::ostream& operator<<(std::ostream& os, const Bien& obj){
    return os << "Bien : " << obj.valor;
}

Ahora veamos sus implementaciones, empecemos con el Rodado:

rodado.h :

 #ifndef RODADO_H
#define RODADO_H

#include <iostream>
#include "bien.h"

class Rodado : public Bien
{
protected:
    int km = 0;
public:
    Rodado();
    double amortizar();
    void setKm(int km);
};

#endif // RODADO_H

rodado.cpp : 

#include "rodado.h"

Rodado::Rodado()
{
}

double Rodado::amortizar(){
    int por = this->km /1000;
    return this->valor * ((0.1) * por);
}

void Rodado::setKm(int km){
    this->km = km;
}

Veamos mueble.h

#ifndef MUEBLE_H
#define MUEBLE_H

#include <iostream>
#include "bien.h"

class Mueble : public Bien
{
protected:
    int anioCreacion = 1900;
public:
    Mueble(int anioCreacion);
    double amortizar();
    void setAnioCreacion(int anioCreacion);
};

#endif // MUEBLE_H

mueble.cpp :

#include "mueble.h"

Mueble::Mueble(int anioCreacion)
{
    this->anioCreacion = anioCreacion;
}

double Mueble::amortizar(){
    int dif = 2017 - this->anioCreacion;
    return this->valor * (dif * 0.05);
}

void Mueble::setAnioCreacion(int anioCreacion){
    this->anioCreacion = anioCreacion;
}

Veamos el inmueble que le puse "Terreno" por lo tanto veremos a terreno.h :

#ifndef TERRENO_H
#define TERRENO_H

#include <iostream>
#include "bien.h"

class Terreno : public Bien
{
public:
    Terreno();
    double amortizar();
};

#endif // TERRENO_H

terreno.cpp :

#include "terreno.h"

Terreno::Terreno()
{
}

double Terreno::amortizar(){
    return 0.0; //no amortiza por eso retorna 0
}

Ahora veremos el gestor contable que no hace mucho en el ejemplo, pero usen la imaginación y piensen que debería guardar los registros, calcular asientos, etc. 

gestorcontable.h :

#ifndef GESTORCONTABLE_H
#define GESTORCONTABLE_H

#include <iostream>
#include "bien.h"

using namespace std;

class GestorContable
{
public:
    GestorContable();
    void imprimir(Bien * unBien);
};

#endif // GESTORCONTABLE_H


gestorcontable.cpp :

#include "gestorcontable.h"

GestorContable::GestorContable()
{
}

void GestorContable::imprimir(Bien * unBien){
    cout << *unBien << " amortizacion : "<< unBien->amortizar() << endl;
}

Como pueden ver el Bien es abstracto y sus especializaciones polimorficas y el gestor contable usa esas características y utiliza el polimorfismo de esta manera no importa que bien deba imprimir, como el calculo de la amortización lo sabe hacer cada bien, cada bien calculara su amortización por lo tanto lo hará correctamente. 

Recuerden que el polimorfismo se refiere a la propiedad por la que es posible enviar mensajes sintácticamente iguales a objetos de tipos distintos. El único requisito que deben cumplir los objetos que se utilizan de manera polimórfica es saber responder al mensaje que se les envía.

Espero que les sirva!!

Antes de despedirme les muestro el main:

 #include <iostream>
#include "bien.h"
#include "mueble.h"
#include "rodado.h"
#include "terreno.h"
#include "gestorcontable.h"

using namespace std;

int main()
{
    GestorContable gestorContable = GestorContable();

    Bien * unTerreno = new Terreno();
    unTerreno->setValor(12000.0);
    gestorContable.imprimir(unTerreno);

    Bien * unRodado = new Rodado();
    Rodado * o = 0;
    // Esto lo hago solo para mostrar un cambio de tipos. 
    if (o = reinterpret_cast<Rodado*> (unRodado)) {
        o->setKm(2450);
    }

    unRodado->setValor(400000.00);
    gestorContable.imprimir(unRodado);

    Bien * unMueble = new Mueble(2000);
    unMueble->setValor(47000.00);
    gestorContable.imprimir(unMueble);

    return 0;
}