send
Grupo de Telegram
play_arrow
Este sitio utiliza cookies propias y de terceros. Si continúa navegando consideramos que acepta el uso de cookies. OK Más Información.

Poliformismo

  • 0 Respuestas
  • 2156 Vistas

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Dharok

  • *
  • Underc0der
  • Mensajes: 110
  • Actividad:
    0%
  • Reputación 0
  • Siempre atento! Aun vivo.
    • Ver Perfil
    • Email
« en: Abril 21, 2010, 05:00:47 pm »
Polimorfismo

Con las funciones virtuales y el polimorfismo es posible diseñar e implementar sistemas que con extensibles con mayor facilidad. Los programas se pueden escribir para que procesen objetos en forma genérica, como objetos de clase base de todas las clases existentes en una jerarquía. Las clases que no existen durante el desarrollo del programa se pueden agregar con poca o sin modificaciones a la parte genérica del programa, siempre y cuando esas clases sean parte de la jerarquía que está siendo procesada en forma genérica. Las únicas partes del programa que necesitarán modificaciones son aquellas que requieren un conocimiento directo de la clase particular que se está agregando a la jerarquía.

Funciones virtual


Si tenemos un conjunto de clases con las formas: Circle, Triangle, Rectangle, Square, que están derivadas de la clase base Shape. En la programación orientada a objetos a cada una de estas figuras se le podría dar la habilidad de dibujarse a sí misma. Aunque cada clase tiene su propia función draw, esta es bastante diferente en cada forma. Cuando se dibuja una forma sin importar el tipo, sería agradable tratar a todas esta formas genéricamente como objetos de la clase base Shape.
Luego, para dibujar cualquier forma podríamos llamar a la función draw de la clase base Shape y dejar que el programa determine dinámicamente (en tiempo de ejecución) cual función draw de la clase derivada se debe utilizar.

Para permitir este tipo de comportamiento declaramos a draw de la clase base como función virtual, y sobreponemos a draw en cada una de las clases derivadas para dibujar la forma adecuada.

Una función de este tipo se declara precediendo la palabra clave virtual, al prototipo de la función, en la definición de la clase, por ejemplo:
Código: You are not allowed to view links. Register or Login
virtual void draw(); Clases base abstractas y clases concretas.

Hay casos en los que es útil definir clases, para las cuales el programador nunca pretende instanciar ningún objeto. Tales clases se denomina clases abstractas. Debido a que estas se utilizan como clases base en situaciones de herencia, normalmente nos referimos a ellas como clases base abstractas. No es posible instanciar un objeto de una clase base abstracta.

El único propósito de una clase abstracta es proporcionar una clase base adecuada a partir de la cual las clases puedan heredar interfaces y/o implementaciones. Las clases de las que se pueden instanciar objetos se denomina clases concretas.

Por ejemplo, se puede tener una clase base abstracta TwoDimwensionalShape y derivar clases concretas tales como Cube, Sphere, Cylinder. Las clases base abstractas son demasiado genéricas como para definir objetos reales, y necesitamos ser mucho más específicos antes de que podamos pensar en instanciar objetos.

Para que una clase sea abstracta se debe declarar como "pura" una o más de sus funciones virtual. Una función virtual pura es aquella que tiene un inicializador = 0 en su declaración, por ejemplo:
Código: You are not allowed to view links. Register or Login
virtual float earningsO const = 0;
Polimorfismo

C++ permite el polimorfismo, que es la habilidad de los objetos de diferentes clases que están relacionados mediante la herencia para responder en forma diferente al mismo mensaje (es decir, a la llamada de función miembro). El mismo mensaje que se envía a muchos tipos de objetos diferentes toma "muchas formas", y de ahí viene el término polimorfismo.

Por ejemplo, si la clase Rectangle se deriva de la clase Quadrilateral, un objeto Rectangle es una versión más específica de un objeto Quadrilateral. Una operación (como el cálculo del perímetro o el área) que puede realizarse en un objeto Quadrilateral también puede realizarse en un objeto Rectangle.

El polimorfismo se implementa por medio de funciones virtual.

Cuando se hace una petición por medio de un apuntador de clase base (o referencia) , para utilizar una función virtual, C++ elige la función sobrepuesta correcta en la clase derivada adecuada que está asociada con ese objeto. Hay muchas veces en que una función miembro no virtual está definida en la clase base y sobrepuesta en una clase derivada. Si a una función de estas se le llama mediante un apuntador de clase base al objeto de la clase derivada, se utiliza la versión de la clase base. Si la función miembro se llama mediante un apuntador de la clase derivada, se utiliza la versión de dicha clase derivada. Este comportamiento no es polimórfico.

Mediante el uso de funciones virtual y el polimorfismo, una llamada de función miembro puede causar que sucedan diferentes acciones, dependiendo del tipo de objeto que recibe la llamada. Esto le da una capacidad expresiva tremenda al programador.

El polimorfismo promueve la extensibilidad: el software que está escrito para llamar al comportamiento polimórfico se escribe en forma independiente de los tipos de objetos a los cuales se envían los mensajes. Por lo tanto los nuevos tipos de objetos que pueden responder a los mensajes existentes se pueden agregar a un sistemas, sin modificar el sistema base.

Un ejemplo concreto

El enunciado del programa sería el siguiente:

Definir una clase Shape que sea una clase base abstracta que contenga la interfaz hacia la jerarquía. Derive a TwoDimensionalShape y ThreeDimensionalShape de la clase Shape, que también serán abstractas. Utilice una función print virtual para enviar a la salida el tipo y dimensiones de cada figura. También incluye funciones virtual area y volume para que estos cálculos puedan realizarse para los objetos de cada clase concreta de la jerarquía.
Escriba un programa controlador que pruebe la jerarquía de la clase Shape.

Y la solución...
Código: C++
  1. #include <iostream.h>
  2. #include <math.h>
  3. #include <conio.h>
  4.  
  5. // clase Shape
  6.  
  7. class Shape {
  8.       public:
  9.          virtual double area() const { return 0.0; }
  10.          virtual double volume() const { return 0.0; }
  11.  
  12.          // funcion virtual pura sobrepuesta en las clases derivadas
  13.          virtual void print() const=0;
  14. };
  15.  
  16. ////////////////////////////////
  17. // clase TwoDimensionalShape ///
  18. ////////////////////////////////
  19.  
  20. class TwoDimensionalShape : public Shape {
  21.       public:
  22.          virtual void print () const=0;
  23. };
  24.  
  25. // clase triangulo
  26. class triangulo : public TwoDimensionalShape {
  27.       double lado1, lado2, lado3;
  28.       public:
  29.          triangulo (double=0.0, double=0.0, double=0.0);
  30.          void fijar_triangulo(double, double, double);
  31.          virtual double area() const;
  32.          virtual void print() const;
  33. };
  34.  
  35. triangulo :: triangulo (double l1, double l2, double l3){
  36.       fijar_triangulo(l1,l2,l3);
  37. }
  38.  
  39. void triangulo :: fijar_triangulo  (double l1, double l2, double l3){
  40.       lado1= l1 > 0 ? l1 : 0;
  41.       lado2= l2 > 0 ? l2 : 0;
  42.       lado3= l3 > 0 ? l3 : 0;
  43. }
  44.  
  45. double triangulo :: area () const {
  46.       double s;
  47.       s=(lado1+lado2+lado3)/2;
  48.  
  49.       return sqrt(s*(s-lado1)*(s-lado2)*(s-lado3));
  50. }
  51.  
  52. void triangulo :: print () const {
  53.       cout << endl << "Triangulo" << endl
  54.       << "Lado 1= " << lado1 << endl
  55.       << "Lado 2= " << lado2 << endl
  56.       << "Lado 3= " << lado3;
  57. }
  58.  
  59. // clase cuadrado
  60. class cuadrado : public TwoDimensionalShape {
  61.       double lado;
  62.       public:
  63.          cuadrado (double=0.0);
  64.          void fijar_cuadrado(double);
  65.          virtual double area() const;
  66.          virtual void print() const;
  67. };
  68.  
  69. cuadrado :: cuadrado (double l) {
  70.       fijar_cuadrado(l);
  71. }
  72.  
  73. void cuadrado :: fijar_cuadrado (double l){
  74.       lado= l>0 ? l : 0;
  75. }
  76.  
  77. double cuadrado :: area () const {
  78.       return lado*lado;
  79. }
  80.  
  81. void cuadrado :: print() const {
  82.       cout << endl << "Cuadrado" << endl
  83.             <<"Lado= " << lado;
  84. }
  85.  
  86. ////////////////////////////////
  87. // clase ThreeDimensionalShape /
  88. ////////////////////////////////
  89.  
  90. class ThreeDimensionalShape : public Shape {
  91.       public:
  92.          virtual void print () const=0;
  93. };
  94.  
  95. // clase cubo
  96. class cubo : public ThreeDimensionalShape {
  97.       double lado;
  98.       public:
  99.          cubo(double=0.0);
  100.          void fijar_cubo(double);
  101.          virtual double area() const;
  102.          virtual double volume() const;
  103.          virtual void print() const;
  104. };
  105.  
  106. cubo :: cubo (double l){
  107.       fijar_cubo(l);
  108. }
  109.  
  110. void cubo :: fijar_cubo (double l){
  111.       lado= l>0 ? l : 0;
  112. }
  113.  
  114. double cubo :: area () const {
  115.       return 6*lado*lado;
  116. }
  117.  
  118. double cubo :: volume () const {
  119.       return lado*lado*lado;
  120. }
  121.  
  122. void cubo :: print() const{
  123.       cout << endl << "Cubo" << endl
  124.             <<"Lado= " << lado;
  125. };
  126.  
  127. // clase paralelepipedo
  128. class paralelepipedo : public ThreeDimensionalShape {
  129.       double largo, ancho, altura;
  130.       public:
  131.          paralelepipedo(double=0.0, double=0.0, double=0.0);
  132.          void fijar_paralelepipedo(double, double, double);
  133.          virtual double area() const;
  134.          virtual double volume() const;
  135.          virtual void print() const;
  136. };
  137.  
  138. paralelepipedo :: paralelepipedo (double l, double a, double h){
  139.       fijar_paralelepipedo(l,a,h);
  140. }
  141.  
  142. void paralelepipedo :: fijar_paralelepipedo (double l, double a, double h){
  143.       largo= l>0 ? l : 0;
  144.       ancho= a>0 ? a : 0;
  145.       altura= h>0 ? h : 0;
  146. }
  147.  
  148. double paralelepipedo :: area () const {
  149.       return 2*largo*ancho + 4*ancho*altura;
  150. }
  151.  
  152. double paralelepipedo :: volume () const {
  153.       return largo*ancho*altura;
  154. }
  155.  
  156. void paralelepipedo :: print() const{
  157.       cout << endl <<"Paralelep¡pedo" << endl
  158.             <<"Largo= " << largo << endl
  159.             <<"Ancho= " << ancho << endl
  160.            <<"Altura= " << altura;
  161. }
  162.  
  163. // llama a funcion virtual a partir del apuntador de clase base
  164. // utilizando enlace dinamico
  165. void virtualViaPointer (const Shape* baseClassPtr){
  166.       baseClassPtr->print();
  167.       cout << endl <<"Area= " << baseClassPtr->area() << endl
  168.             <<"Volumen= " << baseClassPtr->volume() << endl;
  169. }
  170.  
  171. // llama a funcion virtual a partir de referencia a clase base
  172. // utilizando enlace dinamico
  173. void virtualViaReference (const Shape& baseClassRef){
  174.       baseClassRef.print();
  175.       cout << endl <<"Area= " << baseClassRef.area() << endl
  176.             <<"Volumen= " << baseClassRef.volume() << endl;
  177. }
  178.  
  179. // funcion principal
  180. void main(){
  181.       clrscr();
  182.       triangulo t(5.2,6.5,7.1);
  183.       virtualViaPointer (& t);
  184.       virtualViaReference (t);
  185.  
  186.       cuadrado c(8.7);
  187.       virtualViaPointer (&c);
  188.       virtualViaReference (c);
  189.  
  190.       getch();
  191.       clrscr();
  192.  
  193.       cubo cub(8.3);
  194.       virtualViaPointer (&cub);
  195.       virtualViaReference (cub);
  196.  
  197.       paralelepipedo p(4.5,6.7,9.2);
  198.       virtualViaPointer (&p);
  199.       virtualViaReference (p);
  200.  
  201.       getch();
  202. }
« Última modificación: Febrero 08, 2014, 05:20:20 pm por Expermicid »
You are not allowed to view links. Register or Login

 

¿Te gustó el post? COMPARTILO!