UNIDAD 6
POLIMORFISMO
6.1 CONCEPTO DE POLIMORFISMO
6.1 CONCEPTO DE POLIMORFISMO
Permite al programador generar componentes reutilizables de alto nivel que puedan adaptarse a diferentes aplicaciones mediante el cambio de sus partes de bajo nivel.
En programación orientada a objetos se denomina polimorfismo a la capacidad del código de un programa para ser utilizado con diferentes tipos de datos u objetos. También se puede aplicar a la propiedad que poseen algunas operaciones de tener un comportamiento diferente dependiendo del objeto (o tipo de dato) sobre el que se aplican.
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.
Se puede clasificar el polimorfismo en dos grandes clases:
•Polimorfismo dinámico: (o polimorfismo ad hoc) 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 paramétrico) 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
6.2 CLASE BASE ABSTRACTA
En C++ es posible definir clases abstractas. Una clase abstracta, o clase base abstracta (ABC), es una que está diseñada sólo como clase padre de las cuales se deben derivar clases hijas. Una clase abstracta se usa para representar aquellas entidades o métodos que después se implementarán en las clases derivadas, pero la clase abstracta en sí no contiene ninguna implementación solamente representa los métodos que se deben implementar. Por ello, no es posible instanciar una clase abstracta, pero sí una clase concreta que implemente los métodos definidos en ella.
Las clases abstractas son útiles para definir interfaces, es decir, un conjunto de métodos que definen el comportamiento de un módulo determinado. Estas definiciones pueden utilizarse sin tener en cuenta la implementación que se hará de ellos.
En C++ los métodos de las clases abstractas se definen como funciones virtuales puras:
class Abstracta
{
public:
virtual int metodo() = 0;
};
class ConcretaA : public Abstracta
{
Las clases abstractas son útiles para definir interfaces, es decir, un conjunto de métodos que definen el comportamiento de un módulo determinado. Estas definiciones pueden utilizarse sin tener en cuenta la implementación que se hará de ellos.
En C++ los métodos de las clases abstractas se definen como funciones virtuales puras:
class Abstracta
{
public:
virtual int metodo() = 0;
};
class ConcretaA : public Abstracta
{
6.3 SUBPROGRAMAS VIRTUALES
Las funciones virtuales permiten que clases derivadas de una misma base (clases hermanas) puedan tener diferentes versiones de un método. Se utiliza la palabra-clave virtual para avisar al compilador que un método será polimórfico y que en las clases derivadas existen distintas definiciones del mismo.
Para declarar que un método de una clase base es virtual, su prototipo se declara como siempre, pero anteponiendo la palabra-clave virtual, que indica al compilador algo así como: "Será definido más tarde en una clase derivada". Ejemplo:
Sintaxis: virtual void dibujar();
Una función virtual o método virtual es una función cuyo comportamiento, al ser declarado "virtual", es determinado por la definición de una función con la misma cabecera en alguna de sus subclases. Este concepto es una parte muy importante del polimorfismo en la POO.
El concepto de función virtual soluciona los siguientes problemas:
En POO, cuando una clase derivada hereda de una clase base, un objeto de la clase derivada puede ser referido tanto como del tipo de la clase base como del tipo de la clase derivada. Si hay funciones de la clase base redefinidas por la clase derivada, aparece un problema cuando un objeto derivado ha sido cohercionado como del tipo de la clase base. Cuando un objeto derivado es referido como del tipo de la base, el comportamiento de la llamada a la función deseado es ambiguo.
Distinguir entre virtual y no virtual sirve para resolver este problema. Si la función en cuestión es designada "virtual", se llamará a la función de la clase derivada (si existe). Si no es virtual, se llamará a la función de la clase base.
6.4 DESTRUCTORES VIRTUALES
Como cualquier otra función miembro, los destructores pueden ser declarados virtuales. El destructor de una clase derivada de otra cuyo destructor es virtual, también es virtual.
La existencia de un destructor virtual permite que un objeto de una subclase pueda ser correctamente destruido por un puntero a su clase-base.
Ejemplo:
class B { // Superclase (polimórfica)
...
virtual ~B(); // Destructor virtual
};
class D : public B { // Subclase (deriva de B)
...
~D(); // destructor también virtual
};
void func() {
B* ptr = new D; // puntero a superclase asignado a objeto de subclase
delete ptr; // Ok: delete es necesario siempre que se usa new
}
En el ejemplo anterior el mecanismo de llamada de las funciones virtuales permite que el operador delete invoque al destructor correcto, es decir, al destructor ~D de la subclase, aunque se invoque mediante el puntero ptr a la superclase B*. Si el destructor no hubiese sido virtual no se hubiese invocado el destructor derivado ~D, sino el de la superclase ~B, dando lugar a que los miembros privativos de la subclase no hubiesen sido desasignados. Tendríamos aquí un caso típico de "misteriosas" pérdidas de memoria, tan frecuentes en los programas C++ como difíciles de depurar.
BIBLIOGRAFIA
http://www.tutoriales.itsa.edu.mx/programacion1/index.php?mod=concpolimorfismo&ban=0
Las funciones virtuales permiten que clases derivadas de una misma base (clases hermanas) puedan tener diferentes versiones de un método. Se utiliza la palabra-clave virtual para avisar al compilador que un método será polimórfico y que en las clases derivadas existen distintas definiciones del mismo.
Para declarar que un método de una clase base es virtual, su prototipo se declara como siempre, pero anteponiendo la palabra-clave virtual, que indica al compilador algo así como: "Será definido más tarde en una clase derivada". Ejemplo:
Sintaxis: virtual void dibujar();
Una función virtual o método virtual es una función cuyo comportamiento, al ser declarado "virtual", es determinado por la definición de una función con la misma cabecera en alguna de sus subclases. Este concepto es una parte muy importante del polimorfismo en la POO.
El concepto de función virtual soluciona los siguientes problemas:
En POO, cuando una clase derivada hereda de una clase base, un objeto de la clase derivada puede ser referido tanto como del tipo de la clase base como del tipo de la clase derivada. Si hay funciones de la clase base redefinidas por la clase derivada, aparece un problema cuando un objeto derivado ha sido cohercionado como del tipo de la clase base. Cuando un objeto derivado es referido como del tipo de la base, el comportamiento de la llamada a la función deseado es ambiguo.
Distinguir entre virtual y no virtual sirve para resolver este problema. Si la función en cuestión es designada "virtual", se llamará a la función de la clase derivada (si existe). Si no es virtual, se llamará a la función de la clase base.
6.4 DESTRUCTORES VIRTUALES
Como cualquier otra función miembro, los destructores pueden ser declarados virtuales. El destructor de una clase derivada de otra cuyo destructor es virtual, también es virtual.
La existencia de un destructor virtual permite que un objeto de una subclase pueda ser correctamente destruido por un puntero a su clase-base.
Ejemplo:
class B { // Superclase (polimórfica)
...
virtual ~B(); // Destructor virtual
};
class D : public B { // Subclase (deriva de B)
...
~D(); // destructor también virtual
};
void func() {
B* ptr = new D; // puntero a superclase asignado a objeto de subclase
delete ptr; // Ok: delete es necesario siempre que se usa new
}
En el ejemplo anterior el mecanismo de llamada de las funciones virtuales permite que el operador delete invoque al destructor correcto, es decir, al destructor ~D de la subclase, aunque se invoque mediante el puntero ptr a la superclase B*. Si el destructor no hubiese sido virtual no se hubiese invocado el destructor derivado ~D, sino el de la superclase ~B, dando lugar a que los miembros privativos de la subclase no hubiesen sido desasignados. Tendríamos aquí un caso típico de "misteriosas" pérdidas de memoria, tan frecuentes en los programas C++ como difíciles de depurar.
BIBLIOGRAFIA
http://www.tutoriales.itsa.edu.mx/programacion1/index.php?mod=concpolimorfismo&ban=0
No hay comentarios:
Publicar un comentario