Tema 16f. Programación orientada a objetos (6)
Curso: Curso de Pascal, por Nacho Cabanes
Curso de Pascal. Tema 16.6: Programación Orientada a Objetos (6).
Se supone que ya entendemos la base de la OOP en Pascal. Hemos visto como definir y heredar datos o métodos de una "clase" (objeto genérico), cómo redefinirlos, y como crear y manejar "instancias" de esa clase (variables concretas).También hemos tratado los métodos "virtuales", para que el compilador sepa siempre de qué clase "padre" estamos heredando.
En estos casos, necesitábamos emplear en primer lugar un método "constructor", que prepararía una tabla dinámica en la que se van a almacenar todas estas referencias que permiten que nuestro programa sepa a qué método o dato debe acceder en cada momento.
También habíamos comentado que los constructores tenían
otro uso, y que existía algo llamado "destructores".
Eso es lo que vamos a ver hoy.
Vamos a empezar por hacer una variante de nuestro objeto. En ella, el texto va a guardarse de forma dinámica, mediante un puntero.
¿Para qué? Esto es repaso de la lección sobre punteros: la primera ventaja es que no vamos a reservarle memoria del segmento de datos (64K) sino del "heap" (los 640K de memoria convencional). La segunda es que podríamos enlazar unos con otros para crear una lista de textos tan grande como quisiéramos (y la memoria nos permitiese, claro).
No vamos a ver lo de la lista, que ya tratamos en su día, y que no nos interesa hoy especialmente, y vamos a centrarnos en las diferencias que introduciría este puntero en nuestro objeto.
Antes de empezar a usar nuestro objeto, tendremos que reservar memoria para el texto, como hacíamos con cualquier otro puntero:
new( texto );
y cuando terminemos de usar el objeto, debemos liberar la memoria que habíamos reservado:
dispose( texto );
Hasta ahora todo claro, ¿no? Pues vamos a ir fijando conceptos. La orden "new" la debemos usar antes que nada, al inicializar el objeto. Así que crearemos un método encargado de inicializar el objeto (reservar memoria, darle los valores iniciales que nos interesen, etc). Lo llamaré "init", que es el nombre que suele usar Borland, pero se puede elegir cualquier otro nombre.
Entonces, nuestro "init" podría quedar simplemente así:
procedure titulo.init(TextoInicial: string);
begin
new(texto);
{ Reservamos memoria }
texto^ := TextoInicial;
{ Damos valor al texto }
end;
o mejor podemos aprovechar para dar valores iniciales a las demás variables:
procedure 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;
A su vez, tendremos que liberar esta memoria al terminar, para lo que crearemos otro método, que llamaré "done" (hecho) también por seguir el esquema que suele usar Borland. En nuestro caso, que es sencillo, bastaría con
procedure titulo.done;
begin
dispose(texto);
{ Liberamos la memoria }
end;
Vamos a ver cómo iría quedando nuestra clase con estos
cambios:
{--------------------------} { Ejemplo en Pascal: } { } { Objetos y punteros-1 } { OBJETOP1.PAS } { } { Este fuente procede de } { CUPAS, curso de Pascal } { por Nacho Cabanes } { } { Comprobado con: } { - Free Pascal 2.2.0w } { - Turbo Pascal 7.0 } {--------------------------} program ObjetosConPunteros; uses crt; { Usaremos "GotoXY" y TextAttr } type { Aquí definimos nuestro objeto } titulo = object texto: ^string; { El texto que se escribirá } x,y : byte; { En qué posición } color: byte; { El color, claro } procedure 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; { Lo escribe, claro } procedure done; { Libera memoria } end; { --- Desarrollo del objeto Titulo --- } procedure 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; procedure titulo.done; begin dispose(texto); { Liberamos la memoria } end; var t1: titulo; { -- Cuerpo del programa --} begin ClrScr; T1.Init('Por defecto'); T1.Escribe; T1.FijaCoords(37,12); T1.FijaColores(14,2); T1.FijaTexto('Modificado'); T1.Escribe; T1.Done; end.
¿Todo claro? Espero que sí. Hasta ahora no ha habido grandes cambios...
Actualizado el: 08-07-2012 14:17