Deberíamos regañar a nuestro compilador y decirle...
"Mira, no me presupongas cosas. Cuando alguien te
diga Escribe, haz
el favor de mirar quién es, y hacerlo como sabes
que él quiere." ;-)
¿Ah, pero se puede hacer eso? Pues resulta que sí: lo que el compilador hace si no le decimos nada es un enlace estático o "temprano" (en inglés, early binding), en el momento de compilar el programa. Pero también podemos pedirle que haga un enlace dinámico o "tardío" (late binding) justo en el momento de la ejecución, que es lo que nos interesa en estos casos.
De modo que con el enlace dinámico damos una mayor flexibilidad y potencia a la Herencia. Por contra, como los enlaces se calculan en tiempo de ejecución, el programa resultante será ligeramente más lento.
¿Y cómo se hace eso del enlace dinámico? Pues indicando que se trata de un método VIRTUAL. ¿Y eso otro cómo se hace? Fácil:, en la cabecera del método añadimos esa palabra después del punto y coma:
type
{ Aquí definimos nuestro objeto }
titulo = object
[...]
procedure Escribe; virtual;
[...]
end;
Antes de ver cómo quedaría nuestro programa, unos comentarios:
{--------------------------}
{ Ejemplo en Pascal: }
{ }
{ Quinto ejemplo de }
{ Prog. Orientada Obj. }
{ OBJETOS5.PAS }
{ }
{ Este fuente procede de }
{ CUPAS, curso de Pascal }
{ por Nacho Cabanes }
{ }
{ Comprobado con: }
{ - Free Pascal 2.2.0w }
{ - Turbo Pascal 7.0 }
{--------------------------}
program Objetos5; { Nuestro quinto programa en OOP }
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 }
constructor FijaCoords(nuevoX, nuevoY: byte); { <======= }
procedure FijaTexto(mensaje: string); { Idem }
procedure Escribe; virtual; { <===== Lo escribe }
procedure AsignaYEscribe(nuevoTexto:string);
end;
type
TituloColor = object( titulo )
color: byte; { El color, claro }
procedure FijaColores(pluma, fondo: byte); { Pues eso }
procedure Escribe; virtual; { <====== Virtual también }
end;
type
TituloParpadeo = object( tituloColor )
procedure FijaColores(pluma, fondo: byte); { Pues eso }
end;
var
T1: titulo; { Una variable de ese tipo }
T2: tituloColor; { Y otra del otro ;-) }
T3: tituloParpadeo; { Y el que queda }
{ --- Desarrollo del objeto Titulo --- }
constructor 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.Escribe;
begin { Muestra el título }
Gotoxy(X,Y);
Write(Texto);
end;
procedure titulo.AsignaYEscribe(nuevoTexto:string);
begin
FijaTexto(NuevoTexto);
Escribe;
end;
{ --- Métodos específicos de TituloColor --- }
procedure tituloColor.FijaColores(pluma,fondo: byte);
begin { Definimos el procedimiento: }
color := pluma + fondo*16; { Actualiza el color }
end;
procedure tituloColor.Escribe;
begin { Muestra el título }
textAttr := color;
Gotoxy(X,Y);
Write(Texto);
end;
{ --- Métodos específicos de TituloParpadeo --- }
procedure tituloParpadeo.FijaColores(pluma,fondo: byte);
begin { Definimos el procedimiento: }
color := pluma + fondo*16 + 128; { Actualiza el color }
end;
{ -- Cuerpo del programa --}
begin
ClrScr;
T1.FijaCoords(37,12);
T1.AsignaYEscribe('Hola');
T2.FijaCoords(37,13);
T2.FijaColores(14,2);
T2.AsignaYEscribe('Adiós');
T2.Escribe;
T3.FijaCoords(35,14);
T3.FijaColores(15,3);
T3.AsignaYEscribe('Y una más');
end.
Continuará... :-)