Diferencia entre revisiones de «Polimorfismo (informática)»

De Wikipedia, la enciclopedia libre
Contenido eliminado Contenido añadido
m Revertidos los cambios de 192.188.51.12 a la última edición de PoLuX124
Línea 6: Línea 6:
El concepto de polimorfismo se puede aplicar tanto a funciones como a tipos de datos. Así nacen los conceptos de ''funciones polimórficas'' y ''tipos polimórficos''. Las primeras son aquellas funciones que pueden evaluarse o ser aplicadas a diferentes tipos de datos de forma indistinta; los ''tipos polimórficos'', por su parte, son aquellos tipos de datos que contienen al menos un elemento cuyo tipo no está especificado.
El concepto de polimorfismo se puede aplicar tanto a funciones como a tipos de datos. Así nacen los conceptos de ''funciones polimórficas'' y ''tipos polimórficos''. Las primeras son aquellas funciones que pueden evaluarse o ser aplicadas a diferentes tipos de datos de forma indistinta; los ''tipos polimórficos'', por su parte, son aquellos tipos de datos que contienen al menos un elemento cuyo tipo no está especificado.


== Clasificación ==
BLABLABLABLA:
Se puede clasificar el polimorfismo en dos grandes clases:


* '''Polimorfismo dinámico''' (o '''polimorfismo paramétrico''') es aquél en el que el código no incluye ningún tipo de especificación sobre el tipo de datos sobre el que se trabaja. Así, puede ser utilizado a todo tipo de datos compatible.
BLABLABLABLA:
* '''Polimorfismo estático''' (o '''polimorfismo ''ad hoc''''') es aquél en el que los tipos a los que se aplica el polimorfismo deben ser explicitados y declarados uno por uno antes de poder ser utilizados.


El polimorfismo dinámico unido a la herencia es lo que en ocasiones se conoce como '''[[programación genérica]].
BLABLABLABLA:


También se clasifica en herencia por redefinición de métodos abstractos y por método sobrecargado. El segundo hace referencia al mismo método con diferentes parámetros.
BLABLABLABLA:


Otra clasificación agrupa los polimorfismo en dos tipos: '''Ad-Hoc''' que incluye a su vez sobrecarga de operadores y coerción, '''Universal''' (inclusión o controlado por la herencia, paramétrico o genericidad).
BLABLABLABLA:

BLABLABLABLA

NO COPIEN HAGAN SOLOS


== Ejemplo de polimorfismo ==
== Ejemplo de polimorfismo ==

Revisión del 14:38 16 jun 2009

En programación orientada a objetos se denomina polimorfismo a la capacidad que tienen los objetos de una clase de responder al mismo mensaje o evento en función de los parámetros utilizados durante su invocación. Un objeto polimórfico es una entidad que puede contener valores de diferentes tipos durante la ejecución del programa.

En la práctica esto quiere decir que un puntero a un tipo puede contener varios tipos diferentes, no solo el creado. De esta forma podemos tener un puntero a un objeto de la clase Trabajador, pero este puntero puede estar apuntando a un objeto subclase de la anterior como podría ser Márketing, Ventas o Recepcionistas (todas ellas deberían ser subclase de Trabajador).

El concepto de polimorfismo se puede aplicar tanto a funciones como a tipos de datos. Así nacen los conceptos de funciones polimórficas y tipos polimórficos. Las primeras son aquellas funciones que pueden evaluarse o ser aplicadas a diferentes tipos de datos de forma indistinta; los tipos polimórficos, por su parte, son aquellos tipos de datos que contienen al menos un elemento cuyo tipo no está especificado.

Clasificación

Se puede clasificar el polimorfismo en dos grandes clases:

  • Polimorfismo dinámico (o polimorfismo paramétrico) es aquél en el que el código no incluye ningún tipo de especificación sobre el tipo de datos sobre el que se trabaja. Así, puede ser utilizado a todo tipo de datos compatible.
  • Polimorfismo estático (o polimorfismo ad hoc) es aquél en el que los tipos a los que se aplica el polimorfismo deben ser explicitados y declarados uno por uno antes de poder ser utilizados.

El polimorfismo dinámico unido a la herencia es lo que en ocasiones se conoce como programación genérica.

También se clasifica en herencia por redefinición de métodos abstractos y por método sobrecargado. El segundo hace referencia al mismo método con diferentes parámetros.

Otra clasificación agrupa los polimorfismo en dos tipos: Ad-Hoc que incluye a su vez sobrecarga de operadores y coerción, Universal (inclusión o controlado por la herencia, paramétrico o genericidad).

Ejemplo de polimorfismo

En este ejemplo haremos uso del lenguaje C++ para mostrar el polimorfismo. También se hará uso de las funciones virtuales puras de este lenguaje, aunque para que el polimorfismo funcione no es necesario que las funciones sean virtuales puras, es decir, perfectamente el código de la clase "superior" (en nuestro caso Empleado) podría tener código

class Empleado {
protected:
    static const unsigned int SUELDO_BASE = 700; // Supuesto sueldo base para todos

public:
    /* OTROS MÉTODOS */
    virtual unsigned int sueldo() = 0;
};


class Director : public Empleado {
public:
    /* OTROS MÉTODOS */
    unsigned int sueldo() { return SUELDO_BASE*100; }
};


class Ventas : public Empleado {
private:
    unsigned int ventas_realizadas; // Contador de ventas realizadas por el vendedor

public:
    /* OTROS MÉTODOS */
    unsigned int sueldo() { return SUELDO_BASE + ventas_realizadas*60; }
};


class Mantenimiento : public Empleado {
public:
    /* OTROS MÉTODOS */
    unsigned int sueldo() { return SUELDO_BASE + 300; }
};


class Becario : public Empleado {
private:
    bool jornada_completa; // Indica si el becario trabaja a jornada completa

public:
    /* OTROS MÉTODOS */
    unsigned int sueldo() {
        if (jornada_completa) return SUELDO_BASE/2;
        else return SUELDO_BASE/4;
    }
};


/* AHORA HAREMOS USO DE LAS CLASES */
int main() {
    Empleado* e[4]; // Punteros a Empleado
    Director d;
    Ventas v; // Estas dos las declararemos como objetos normales en la pila
    
    e[0] = &d; // Asignamos a un puntero a Empleado la dirección de un objeto del tipo Director
    e[1] = &v; // Lo mismo con Ventas
    e[2] = new Mantenimiento();
    e[3] = new Becario();
    
    unsigned int sueldo = 0;
    for (int i = 0; i < 4; ++i) sueldo += e[i]->sueldo();
    
    cout << "Este mes vamos a gastar " << sueldo << " dinero en sueldos" << endl;
}

Polimorfismo desde una interfaz

Aunque el polimorfismo es el mismo se aplique donde se aplique, el modo en que se aplica desde una interfaz puede resultar un poco más oscuro y difícil de entender. Se expone un sencillo ejemplo comentado para entender como funciona aplicado desde una interfaz, primero se escribe el código y luego se comenta el funcionamiento. Nota: para no enturbiar el código en exceso, todo lo que no se declara privado se sobreentiende público.

   ' Declaramos una interfaz llamada IOperar y declaramos una función llamada Operar 
        ' que implementarán las clases deseadas:
   Interface IOperar
       Function Operar(valor1 as integer, valor2 as integer) as long
   End Interface
 
  ' Declaramos una clase que trabaja más alejada del usuario y que contendría funciones comunes
            ' para las siguiente clase, si no fueran idénticas irían en la interfaz, 
            ' pero al caso de mostrar el polimorfismo se suponen idénticas:
  Class Operacion
      Function Calcular(clasellamante as Object) as Long 
          ' aquí iría el código común a todas las operaciones.... que llaman a esa función
          ' por ejemplo recoger los 2 valores de la operación, chequear que están en el rango deseado, etc.

          ' se supone que la función inputValor recoge un valor de algún sitio
          valor1 as integer = inputValor() 
          valor2 as integer = inputValor()
     
          op as New IOperar = clasellamante
          Return op.Operar(valor1,valor2) 'AQUÍ es donde se utiliza el polimorfismo.
      End Function
  End Class
  ' Declaramos 2 clases: Sumar y Resta que implementan la interfaz y que llaman a la clase Operacion:
  Class Sumar
      Implements IOperar
      Private Function Operar(valor1 as Integer, valor2 as Integer) as Long Implements IOperar.Operar
          Return valor1 + valor2
      End Function
     
      Function Calcular() as Long
          op as New operacion
          Return op.Calcular(Me) ' se está llamando a la función 'Calcular' de la clase 'Operación'
      End Function
  End Class
  ' segunda clase....
  Class Restar
      Implements IOperar
      Private Function Operar(valor1 as Integer, valor2 as Integer) as Long Implements IOperar.Operar
          Return valor1 - valor2
      End Function
 
      Function Calcular() as Long
          op as New operacion
          Return op.Calcular(Me) ' se está llamando a la función 'Calcular' de la clase 'Operación'
      End Function
  End Class
  • Analicemos ahora el código para entender el polimorfismo expuesto en la interfaz: La interfaz expone un método que puede ser implementado por las diferentes clases, normalmente relacionadas entre si. Las clases Sumar y Restar implementan la interfaz pero el método de la interfaz lo declaramos privado para evitar ser accedido libremente y además tienen un método llamado Calcular que llama a la clase Operacion donde tenemos otro método con el mismo nombre. Es esta clase última la que realiza el polimorfismo y debe fijarse como es a través de una instancia de la interfaz que llama al método operar. La interfaz sabe a qué método de qué clase llamar desde el momento que asignamos un valor a la variable OP en el método Calcular de la clase Operacion, que a se vez recibió la referencia del método Calcular desde la clase que la llama, sea está cual sea se identifica a sí misma, mediante la referencia Me ó This según el lenguaje empleado. Debe notarse que la instancia de la interfaz accede a sus métodos aunque en sus clases se hayan declarado privadas.

Ventajas del polimorfismo frente a la sobrecarga

El polimorfismo como se muestra en el ejemplo anterior, suele ser bastante ventajoso aplicado desde las interfaces, ya que permite crear nuevos tipos sin necesidad de tocar las clases ya existentes (imaginemos que deseamos añadir una clase Multiplicar), basta con recompilar todo el código que incluye los nuevos tipos añadidos. Si se hubiera recurrido a la sobrecarga durante el diseño exigiría retocar la clase anteriormente creada al añadir la nueva operación Multiplicar, lo que además podría suponer revisar todo el código donde se instancia a la clase.