‒ Constructores Virtuales.
Al igual que los métodos virtuales, existen también constructores virtuales, la utilidad de los constructores virtuales, viene de la mano con el uso de referencias de clase.
Cuando sobre-escribimos los constructores de las clases descendientes, y usamos una referencia de clase para crearlos este usará siempre el constructor de la clase padre, ignorando los constructores de las clases descendientes. Así pasemos en la referencia de clase una clase descendiente para crearlo, veamos a continuación un ejemplo:
‒
Descargar
{$codepage utf8}
{$mode objfpc}
Program Prueba;
Type
TClase01=class
Constructor crear;
End;
TClase02=class(TClase01)
Constructor crear;
End;
TRef=Class of TClase01;
Constructor TClase01.crear;
Begin
Writeln('Clase01')
End;
Constructor TClase02.crear;
Begin
Writeln('Clase02')
End;
Var A:TClase01;
Ref:TRef;
Begin
Ref:=TClase01;
A:=Ref.crear;
Ref:=TClase02;
A:=Ref.crear
End.
Código fuente 1: Uso de constructores no virtuales.
Descargar
Como se puede ver la referencia de clase siempre ejecutará el constructor de la clase padre, que es TClase01, y creará los dos objetos como si fueran TClase01, ignorando al que hace referencia a TClase02.
Para remediar esta situación es que se usan los Constructores virtuales, que funcionan de manera similar a los métodos virtuales, a continuación el ejemplo anterior con los cambios realizados.
‒
Descargar
{$codepage utf8}
{$mode objfpc}
Program Prueba;
Type
TClase01=class
Constructor crear;virtual;
End;
TClase02=class(TClase01)
Constructor crear;override;
End;
TRef=Class of TClase01;
Constructor TClase01.crear;
Begin
Writeln('Clase01')
End;
Constructor TClase02.crear;
Begin
Writeln('Clase02')
End;
Var A:TClase01;
Ref:TRef;
Begin
Ref:=TClase01;
A:=Ref.crear;
Ref:=TClase02;
A:=Ref.crear
End.
Código fuente 2: Uso de constructores virtuales.
Descargar
Al igual que los métodos virtuales, se usan las palabras reservadas virtual y override.
La utilidad de los constructores virtuales esta en la necesidad de crear objetos cuando no se conoce el objeto que se desea construir hasta que se lo necesite. Revisemos el siguiente ejemplo, en donde cada constructor de los aviones tiene su propio contador, cada vez que se crea un avión aleatoriamente.
‒
Descargar
{$codepage utf8}
{$mode objfpc}
Uses sysutils;
Type
TClassAvion=Class of TAvion;
TAvion=class
class var
FAviones:integer; //atributos o variables de clase
var
constructor create(Nombre:string);virtual;
End;
TAvComercial=class(TAvion)
class var
FAvionesComerciales:integer;
Constructor create(Nombre:string);override;
End;
TAvGuerra=class(TAvion)
class var
FAvionesGuerra:integer;
Constructor create(Nombre:string);override;
End;
TEscenario=Class
Ref:TClassAvion;
A:array of TAvion;
Procedure GenerarAvionesAzar;
End;
Constructor TAvion.create(Nombre:string);
Begin
Faviones +=1;
Writeln('[',Nombre,'] Creado Avion Generico ');
End;
Constructor TAvComercial.create(Nombre:string);
Begin
FAvionesComerciales+=1;
Writeln('[',Nombre,'] Creado Avion Comercial ');
End;
Constructor TAvGuerra.create(Nombre:string);
Begin
FAvionesGuerra+=1;
Writeln('[',Nombre,'] Creado Avion Guerra ');
End;
Procedure TEscenario.GenerarAvionesAzar;
Var i,j,c:integer;
Begin
randomize;
c:=random(20);
setlength(A,c);
for i:=1 to c-1 do
Begin
j:=random(3);
ref:=TAvion;
if j=1 then ref:=TAvComercial;
If j=2 then ref:=TAvGuerra;
A[i]:=ref.create(IntToStr(i));
End;
Writeln(TAvion.FAviones,' aviones genericos creados');
Writeln(TAvComercial.FAvionesComerciales,' aviones comerciales creados');
Writeln(TAvGuerra.FAvionesGuerra,' aviones de guerra creados');
End;
Var Escenario:TEscenario;
Begin
Escenario:=TEscenario.create;
Escenario.GenerarAvionesAzar
End.
Código fuente 3: Uso de constructores virtuales con el ejemplo de aviones.
Descargar
En este ejemplo cada constructor incrementa el contador correspondiente de cada avión cada vez que este es creado, si en caso los constructores de las clases TAvComercial y TAvGuerra, no se sobrescriben usando virtual y override, entonces los contadores FAvionesComerciales y FAvionesGuerra no se incrementarían, y todos los aviones creados mostrarían el mensaje del constructor de la clase TAvion.