Disponible la nueva versión "donationware" 7.3 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


4.11.8  Clases polimórficas

§1  Sinopsis

En la introducción a la POO ( 1.1) se señaló que uno de sus pilares básicos es el polimorfismo; la posibilidad de que un método tenga el mismo nombre y resulte en el mismo efecto básico pero esté implementado de forma distinta en clases distintas de una jerarquía. En este capítulo y siguiente describiremos los mecanismos que utiliza C++ para hacer esto posible. La explicación involucra varios conceptos estrechamente relacionados entre si: el de función virtual ( 4.11.8a), el enlazado dinámico ( 1.4.4) y el de clase polimórfica que analizamos en este capítulo.

§2  Clases polimórifcas

Como se verá muy claramente en el ejemplo que sigue, las técnicas de POO necesitan a veces de clases con una interfaz muy genérica que deben servir a requerimientos variados (de ahí el nombre "polimórficas"), por lo que no es posible establecer "a priori" el comportamiento de algunos de sus métodos, que debe ser definido más tarde en las clases derivadas. Dicho en otras palabras: en ciertas súper-clases, denominadas polimórficas, solo es posible establecer el prototipo para algunas de sus funciones-miembro, las definiciones deben ser concretadas en las subclases, y generalmente son distintas para cada descendiente [1]. Estas funciones-miembro son denominadas virtuales y C++ establece para ellas un mecanismo de enlazado especial (dinámico) que posibilita que las diversas subclases de la familia ofrezcan diferentes comportamientos (diferencias que dan lugar precisamente al comportamiento polimórfico de la súper clase).

  Para que una clase sea polimórfica debe declarar o heredar al menos una función virtual o virtual pura (aclararemos este concepto más adelante 4.11.8a). En este último caso la clase polimórfica es además abstracta ( 4.11.8c). Así pues, clases polimórficas son aquellas pensadas para servir de base de una jerarquía en las que sus miembros (subclases) disponen de una misma interfaz, pero son implementadas para servir propósitos distintos en circunstancias distintas (la interfaz es polimórfica). Lo que se consigue incluyendo en ellas unos métodos especiales (virtuales) que se definen de forma diferente en cada subclase. Es decir, el polimorfismo presupone la existencia de una súper-clase polimórfica de la que deriva más de una subclase.


§2.1  Generalmente las clases polimórficas no se utilizan para instanciar objetos directamente [2], sino para derivar otras clases en las que se detallan los distintos comportamientos de las funciones virtuales. De esta segunda generación si se instancian ya objetos concretos. De esta forma, las clases polimórficas operan como interfaz para los objetos de las clases derivadas.

Es clásico el caso de la clase Poligono, para manejar Cuadrados, Círculos, Triángulos, etc.

class Poligono {
  Punto centro;
  Color col;
  ...
  public:
  point getCentro() { return centro; }
  void putCentro(Punto p) { centro = p; }
  void putColor(Color c) { col = c; }
  void mover(Punto a) { borrar(); centro = a; dibujar(); }
  virtual void borrar(); 
  virtual void dibujar();
  virtual void rotar(int);
  ...
};


Esta clase es polimórfica;  Punto y Color son a su vez sendas clases auxiliares. Los métodos borrar, dibujar y rotar (que se declaran virtuales) tienen que ser definidos más tarde en las clases derivadas, cuando se sepa el tipo exacto de figura, ya que no se requiere el mismo procedimiento para rotar un triángulo que un círculo. De esta clase no es posible derivar objetos.

Para definir una figura determinada, por ejemplo un círculo, lo primero es derivar una clase concreta de la clase genérica de las figuras (en el ejemplo la clase Circulo). En esta subclase, que en adelante representará a todos los círculos, debemos definir el comportamiento específico de los métodos que fueron declarados "virtuales" en la clase base.

class Circulo : public Poligono {   // la clase circulo deriva de Poligono
   int radio;         // propiedad nueva (no existe en la superclase)
   public:
     void borrar() { /* procesos para borrar un círculo */ }
     void dibujar() { /* procesos para dibujar un círculo */ }
     void rotar(int) {}              // en este caso una función nula!
     void putRadio(int r) { radio = r; }
};


El último paso será instanciar un objeto concreto (un círculo determinado). Por ejemplo:

Circulo circ1;
Punto centr1 = {1, 5};
circ1.putCentro(centr1);
circ1.putColor( rojo );
circ1.putRadio( 25 );
circ1.dibujar();


§2.2  Veremos que, además de la herencia y las funciones virtuales, hay otro concepto íntimamente ligado con la cuestión: las funciones dinámicas ( 4.11.8b), aunque esta es una particularidad de C++Builder y como tal no soportado por el Estándar.

  Inicio.


[1]  Los únicos tipos que soportan polimorfismo son class y struct.

[2]  Decimos "generalmente" porque cuando se tiene la certeza de que no se instanciarán objetos de la superclase, se recurre a declararla abstracta.