Curso de Pascal. Tema 16.8: Programación Orientada a Objetos (8).

Ahora nos hará falta un nuevo "new" para el objeto y un nuevo "dispose":

new(t1)
t1^.init('Texto de ejemplo');
...
t1^.done;
dispose(t1);

Pero aún hay más: al liberar un objeto dinámico, existe una palabra clave que nos garantiza que se va a liberar la cantidad de memoria justa (especialmente si nuestros objetos dinámicos contienen a su vez datos dinámicos, etc).  Es la palabra "destructor" que reemplaza a "procedure" (igual que hacía "constructor").

Entonces, nuestro último método quedaría

destructor titulo.done;
begin
  dispose(texto);                     { Liberamos la memoria }
end;

Se puede definir más de un destructor para una clase, y como es fácil que lo heredemos sin reescribirlo, puede resultar conveniente definirlo siempre como "virtual".

Vamos a ver cómo quedaría ahora nuestro programita:


 {--------------------------} 
 {  Ejemplo en Pascal:      } 
 {                          } 
 {    Objetos y punteros-3  } 
 {    OBJETOP3.PAS          } 
 {                          } 
 {  Este fuente procede de  } 
 {  CUPAS, curso de Pascal  } 
 {  por Nacho Cabanes       } 
 {                          } 
 {  Comprobado con:         } 
 {    - Free Pascal 2.2.0w  }
 {    - Turbo Pascal 7.0    } 
 {--------------------------}
 program ObjetosConPunteros3;
 uses crt;                            { Usaremos "GotoXY" y TextAttr }
 type                                { Aquí definimos nuestro objeto } 
   pTitulo = ^titulo; 
   titulo = object 
     texto: ^string;                     { El texto que se escribirá } 
     x,y : byte;                                   { En qué posición } 
     color: byte;                                  { El color, claro } 
     constructor init(TextoInicial: string);            { Inicializa } 
     procedure FijaCoords(nuevoX, nuevoY: byte);          { Pues eso } 
     procedure FijaTexto(mensaje: string);                    { Idem } 
     procedure FijaColores(pluma,fondo: byte);           { y lo otro } 
     procedure Escribe; virtual;                 { Lo escribe, claro } 
     destructor done; virtual;                      { Libera memoria } 
   end;
 { --- Desarrollo del objeto Titulo --- }
 constructor titulo.init(TextoInicial: string); 
 begin 
   new(texto);                         { Reservamos memoria } 
   texto^ := TextoInicial;             { Damos valor al texto } 
   x :=1 ; y := 1;                     { Coordenadas por defecto } 
   color := 7;                         { Gris sobre negro }
 end;
 procedure titulo.FijaCoords(nuevoX, nuevoY: byte); 
 begin                                 { Definimos el procedimiento: } 
   x := nuevoX;                          { Actualiza las coordenadas } 
   y := nuevoY; 
 end;
 procedure titulo.FijaTexto(mensaje: string); 
 begin                                          { Actualiza el texto } 
   Texto^ := Mensaje; 
 end;
 procedure titulo.FijaColores(pluma,fondo: byte); 
 begin                                 { Definimos el procedimiento: } 
   color := pluma + fondo*16;                   { Actualiza el color } 
 end;
 procedure titulo.Escribe; 
 begin 
   TextAttr := color;                             { Muestra el título } 
   Gotoxy(X,Y); 
   Write(Texto^); 
 end;
 destructor titulo.done; 
 begin 
   dispose(texto);                     { Liberamos la memoria } 
 end;
 var 
   t1: pTitulo;
 { -- Cuerpo del programa --} 
 begin 
   ClrScr; 
   new(T1); 
   T1^.Init('Por defecto'); 
   T1^.Escribe; 
   T1^.FijaCoords(37,12); 
   T1^.FijaColores(14,2); 
   T1^.FijaTexto('Modificado'); 
   T1^.Escribe; 
   T1^.Done; 
   dispose(T1); 
 end. 

Finalmente, Turbo Pascal amplía también la sintaxis de la orden "new" para permitir reservar la memoria e inicializar el objeto en un solo paso, de modo que

new(T1);
T1^.Init('Por defecto');

se puede escribir como

new(T1, Init('Por defecto'));

es decir, ejecutamos "new" con dos parámetros: el objeto para el que queremos reservar la memoria, y el procedimiento que se va a encargar de inicializarlo.  Lo mismo ocurre con "dispose".  Así, el cuerpo de nuestro programa queda:

begin
  ClrScr;
  new(T1, Init('Por defecto'));
  T1^.Escribe;
  T1^.FijaCoords(37,12);
  T1^.FijaColores(14,2);
  T1^.FijaTexto('Modificado');
  T1^.Escribe;
  dispose(T1, Done);
end.
 

Pues esto es la OOP en Pascal.  Este último apartado y el anterior (objetos dinámicos y métodos virtuales) son, a mi parecer, los más difíciles y los más pesados.  No todo el mundo va a utilizar objetos dinámicos, pero es raro no tener que usar nunca métodos virtuales.

Así que mi consejo es el de siempre: experimentad, que muchas veces es como más se aprende.