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.