16.3: Problemas con la herencia.
Hemos visto una introducción a los objetos, y hemos empezado a manejar
la herencia y el polimorfismo. Ahora vamos a ver algo que puede parecer
desconcertante y que nos ayudará a entender qué son los métodos
virtuales (espero)
Por cierto, este tema es "denso". No intentes "dominarlo" a la
primera lectura. Si te pierdes, prueba a releerlo entero. Si
te siguen quedando dudas, pregunta...
Habíamos creado nuestro objeto "Titulo". Despues introdujimos
otro llamado "TituloColor" que aprovechaba parte de las definiciones del
primero, le añadimos cosas nuevas y retocamos las que nos interesaron.
Ahora vamos a crear un "TituloParpadeo", que será exactamente
igual que "TituloColor", con la diferencia de que además el texto
parpadeará.
Si alguien ha trabajado un poco con los colores en modo texto, sabrá
que el único cambio que tenemos que hacer es sumar 128 al color
que vamos a usar (o si lo preferís ver así: fijamos el primer
bit de los atributos, que es el que indica el parpadeo).
Entonces crearemos un nuevo objeto que heredará todo de "TituloColor"
y sólo redefinirá "FijaColores". El programa queda
así:
{--------------------------}
{ Ejemplo en Pascal:
}
{
}
{ Tercer ejemplo de
}
{ Prog. Orientada Obj. }
{ OBJETOS3.PAS
}
{
}
{ Este fuente procede de }
{ CUPAS, curso de Pascal }
{ por Nacho Cabanes
}
{
}
{ Comprobado con:
}
{ - Turbo Pascal 7.0
}
{--------------------------}
program Objetos3;
{ Nuestro tercer 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 }
procedure FijaCoords(nuevoX, nuevoY: byte);
{ Pues eso }
procedure FijaTexto(mensaje: string);
{ Idem }
procedure Escribe;
{ Lo escribe, claro }
end;
type
TituloColor = object( titulo )
color: byte;
{ El color, claro }
procedure FijaColores(pluma, fondo: byte);
{ Pues eso }
procedure Escribe;
{ Lo escribe de distinta forma }
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 --- }
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.Escribe;
begin
{ Muestra el título }
Gotoxy(X,Y);
Write(Texto);
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.FijaTexto('Hola');
T1.Escribe;
T2.FijaCoords(37,13);
T2.FijaColores(14,2);
T2.FijaTexto('Adiós');
T2.Escribe;
T3.FijaCoords(35,14);
T3.FijaColores(15,3);
T3.FijaTexto('Y una más');
T3.Escribe;
end.
No hemos definido Escribe para TituloParpadeo y sin embargo lo hemos
usado. Claro, es que tampoco hacía falta redefinirlo.
Recordemos la definición de TituloColor.Escribe:
procedure tituloColor.Escribe;
begin
textAttr := color; { Asignamos el color
}
Gotoxy(X,Y);
{ Vamos a la posición adecuada }
Write(Texto);
{ Y escribimos el texto }
end;
Todo nos sirve: queremos hacer eso mismo, pero con "TituloParpadeo"
en vez de con "TituloColor". No hay problema, el compilador se da
cuenta de que es T3 quien intenta escribir, y toma las variables X, Y,
Color y Texto apropiadas.
Así tenemos el primer rótulo "Hola", con letras grises
y fondo negro. El segundo, "Adiós", tiene letras amarillas y fondo
verde. El tercero, "Y una más", tiene fondo azul claro y letras
blancas parpadeantes.
Inciso momentáneo: En OOP se suele llamar CLASE
a una definición genérica de un objeto, como en nuestro caso
"TituloColor" e INSTANCIA a una variable concreta que pertenece
a ese clase, como T2 en nuestro ejemplo. Como ejemplo más
general, "persona" sería una clase, formada por muchos individuos
con unas características comunes, mientras que "Pepe" sería
un objeto (sin ánimo de ofender) de la clase persona, una
instancia de esa clase.
Así me puedo permitir el lujo de usar las palabras "clase" e
"instancia" cuando quiera y ya nadie tiene excusa para protestar... O
|