‒ Herencia - Polimorfismo por sobre-escritura - Compatibilidad entre objetos.

La herencia es una característica, que permite que una clase nueva se pueda crear a partir de otra existente. La herencia permite que una clase nueva contenga los métodos y atributos de otra clase, a la clase nueva generalmente se le llama subclase y la clase del cual se heredan sus métodos y atributos se le suele llamar clase primaria o clase padre.

La ventaja de la herencia es la posibilidad de definir atributos y métodos nuevos para las subclases que se crean, que luego se pueden usar con los métodos y atributos heredados de la clase padre.

Además una subclase puede ser usada como clase padre para crear otras clases, y estas a su vez también se pueden usar como clases padres, y de ese modo se puede crear una jerarquía de clases especializada. En donde se denomina superclase a la clase que es el inicio de una jerarquía de clases. En freepascal, la herencia se indica al principio de la definición de una clase:

   TReal = class(TComplejo)
   
   End;

TReal es una clase que tiene exactamente los mismos métodos y atributos de la clase TComplejo. Los métodos, constructores y destructores de una clase padre pueden ser reemplazados o sobre-escritos por los métodos, constructores y destructores de una subclase, de ese modo se puede hacer que la subclase use los mismos métodos, constructores y destructores que la clase padre pero su comportamiento o funcionamiento será diferente. Cuando se sobre-escribe un método para cambiar el comportamiento de una subclase, entonces se dice que se está usando polimorfismo por sobre-escritura.

Para sobre-escribir un método o constructor, este debe tener el mismo nombre y la misma cantidad de parámetros, los parámetros pueden tener otro identificador y distinto tipo de dato.

A la clase TReal se le puede añadir un constructor con el mismo nombre que crear y un nuevo método ObtCad, que reemplaza ó sobre-escribe al método y constructor heredado de su clase padre. A continuación la implementación de la clase Real, que se debe guardar en el archivo Reales.pp:


Descargar
{$codepage utf8}
{$mode objfpc}
Unit Reales;
Interface
Uses Complejos03;
Type
 TReal = class(TComplejo)
    //sobreescribe Crear(i:double), que crea un número complejo imaginario puro
    Constructor Crear(r:double);
    Function ObtCad(dec:integer):string;
 End;

Implementation

    Constructor TReal.Crear(r:double);
      Begin
        ParteReal:=r;
        ParteImag:=0
      End;

    Function TReal.ObtCad(dec:integer):string;
      var p:string;
      Begin
          Str(ParteReal:0:dec,p);
          ObtCad := p
      End;

End.
Código fuente 9: Unidad Reales.pp con la clase TReal.
Descargar

A continuación el programa que usa las unidades Complejos y Reales:


Descargar
{$codepage utf8}
{$mode objfpc}
Uses Complejos03,Reales;
Var A,B,C:TComplejo;
    D,E,F:TReal;
Begin

   A:=TComplejo.Crear(10,4);
   B:=TComplejo.Crear(3);
   C:=TComplejo.Crear(A.ObtReal,A.ObtImag);
   Writeln('A=',A.ObtCad(0));
   Writeln('B=',B.ObtCad(0));
   C.Adicion(B);
   Writeln('A+B=',C.ObtCad(0));
   C.Crear(A.ObtReal,A.ObtImag);
   C.Multiplicacion(B);
   Writeln('A*B=',C.ObtCad(0));

   D:=TReal.Crear(2);
   E:=TReal.Crear(3);
   F:=TReal.Crear(D.ObtReal);
   Writeln('D=',D.ObtCad(0));
   Writeln('E=',E.ObtCad(0));
   F.Adicion(E);
   Writeln('D+E=',F.ObtCad(0));
   F.Crear(D.ObtReal);
   F.Multiplicacion(E);
   Writeln('D*E=',F.ObtCad(0))
End.
Código fuente 10: Uso de las unidades Complejos03 y Reales.
Descargar

Gracias al polimorfismo por sobre-escritura se ha logrado que los objetos que se crean de la clase TReal, interpreten adecuadamente el método ObtCad que es sobre-escrito por la clase TReal.

Cuando se sobre-escribe un método, se puede llamar al método, destructor o constructor anteriormente sobre-escrito, y para ello existe una palabra reservada inherited, que permite hacer esta tarea.

Inherited sin parámetro llama al constructor, destructor o método sobre-escrito con el mismo nombre del método que sobre-escribe al método heredado. Si este método tiene parámetros, usará los parámetros del método sobre-escrito.

Cuando tiene un nombre seguido después de inherited llama al método sobre-escrito sobrecargado con un nombre diferente.

Cuando se usa inherited con constructores, es recomendado usar inherited al inicio del código de un constructor y en el caso de destructores al final.

El siguiente programa es un ejemplo del uso de inherited:


Descargar
{$codepage utf8}
{$mode objfpc}
Type
  TClase01=Class
     Procedure Escribe;
  End;

  TClase02=Class(TClase01)
     Procedure Escribe;
     Procedure Escribe(cad:string);
  End;

  TClase03=Class(TClase02)
     Procedure Escribe;
  End;

  Procedure TClase01.Escribe;
    Begin
      Writeln('Base 01')
    End;

  Procedure TClase02.Escribe;
    Begin
      Writeln('Base 02')
    End;

  Procedure TClase02.Escribe(cad:string);
    Begin
      Writeln('Base 02 ',cad)
    End;

  Procedure TClase03.Escribe;
   Begin
    inherited;                  //Llama al inmediato con el mismo nombre
    inherited Escribe('hola');  //Llama al sobrecargado
    Writeln('Base 03')
   End;

Var B01:TClase01;
    B02:TClase02;
    B03:TClase03;

Begin
  B01:=TClase01.create;
  B02:=TClase02.create;
  B03:=TClase03.create;
  Writeln('---1---');
  B01.Escribe;
  Writeln('---1---');
  Writeln('---2---');
  B02.Escribe;
  Writeln('---2---');
  Writeln('---3---');
  B03.Escribe;
  Writeln('---3---')
End.
Código fuente 11: Uso de inherited.
Descargar