Un constructor es un método especial de una clase que tiene por objetivo inicializar campos de la clase (normalmente otros objetos)
El método Create heredado de la clase TObject es un constructor y en muchas situaciones lo reescribimos en las subclases. Puede haber otros constructores con otros nombres en la clase.
El destructor es otro método de la clase que será el último que se ejecute y tiene por objetivo liberar espacio de campos de la clase.
La clase TObject tiene un destructor llamado Destroy que es el que generalmente reescribimos en las subclases.
Tanto constructores y destructores de clase son opcionales, como ha sucedido en ejemplos anteriores donde no hemos definido estos tipos especiales de métodos.
Con un ejemplo veremos como plantear constructor y destructor de una clase.
Un banco tiene 3 clientes que pueden hacer depósitos y extracciones. También el banco requiere que al final del día calcule la cantidad de dinero que hay depositada.
Lo primero que hacemos es identificar las clases:
Podemos identificar la clase TCliente y la clase TBanco.
Luego debemos definir los campos y los métodos de cada clase:
TCliente
campos
Nombre
Monto
métodos
Depositar
Extraer
Imprimir
TBanco
campos
3 Cliente (3 objetos de la clase TCliente)
métodos
constructor
Operar
DepositosTotales
destructor
program Proyecto135;
{$APPTYPE CONSOLE}
type
TCliente = class
Nombre: String;
Monto: Double;
constructor Create(nom: String);
procedure Depositar(mon: Double);
procedure Extraer(mon: Double);
procedure Imprimir;
end;
TBanco = class
Cliente1: TCliente;
Cliente2: TCliente;
Cliente3: TCliente;
constructor Create;
destructor Destroy; Override;
procedure Operar;
procedure DepositosTotales;
end;
constructor TCliente.Create(nom: string);
begin
inherited Create;
Nombre := nom;
Monto := 0;
end;
procedure TCliente.Depositar(mon: Double);
begin
Monto := Monto + mon
end;
procedure TCliente.Extraer(mon: Double);
begin
Monto := Monto - mon;
end;
procedure TCliente.Imprimir;
begin
WriteLn('El cliente ', Nombre, ' tiene depositado el monto de ', Monto:0:2);
end;
constructor TBanco.Create;
begin
inherited Create;
Cliente1 := TCliente.Create('Juan');
Cliente2 := TCliente.Create('Ana');
Cliente3 := TCliente.Create('Pedro');
end;
destructor TBanco.Destroy;
begin
Cliente1.Free;
Cliente2.Free;
Cliente3.Free;
inherited Destroy;
end;
procedure TBanco.Operar;
begin
Cliente1.Depositar(100);
Cliente2.Depositar(300);
Cliente3.Depositar(400);
Cliente1.Extraer(50);
end;
procedure TBanco.DepositosTotales;
var
suma: Double;
begin
suma := Cliente1.Monto + Cliente2.Monto + Cliente3.Monto;
Cliente1.Imprimir;
Cliente2.Imprimir;
Cliente3.Imprimir;
WriteLn('El banco tiene un total de ', suma:0:2);
end;
var
Banco1: TBanco;
begin
Banco1 := TBanco.Create;
Banco1.Operar;
Banco1.DepositosTotales;
Banco1.Free;
ReadLn;
end.
La clase TCliente define el constructor Create que recibe como parámetro un String con el nombre del cliente:
TCliente = class
Nombre: String;
Monto: Double;
constructor Create(nom: String);
procedure Depositar(mon: Double);
procedure Extraer(mon: Double);
procedure Imprimir;
end;
El algoritmo del constructor inicia el campo Nombre con el valor que llega en el parámetro y el campo Monto carga el valor cero:
constructor TCliente.Create(nom: string); begin inherited Create; Nombre := nom; Monto := 0; end;
El constructor como dijimos tiene por objetivo cargar algunos o todos los campos, en nuestro ejemplo cargamos Nombre y Monto.
La clase TBanco define 3 campos de tipo TCliente. Esto significa que en algún momento debemos crear esos tres objetos y en otro liberar el espacio ocupado por los mismos:
TBanco = class
Cliente1: TCliente;
Cliente2: TCliente;
Cliente3: TCliente;
constructor Create;
destructor Destroy; Override;
procedure Operar;
procedure DepositosTotales;
end;
En el constructor Create procedemos a iniciar los tres campos:
constructor TBanco.Create;
begin
inherited Create;
Cliente1 := TCliente.Create('Juan');
Cliente2 := TCliente.Create('Ana');
Cliente3 := TCliente.Create('Pedro');
end;
Como vemos llamamos al constructor Create que creamos en la clase TCliente pasando como dato un String que representa el nombre del cliente.
El constructor Create de la clase TBanco será el primer método que se ejecutará, luego el método operar:
procedure TBanco.Operar; begin Cliente1.Depositar(100); Cliente2.Depositar(300); Cliente3.Depositar(400); Cliente1.Extraer(50); end;
Como los tres objetos Cliente1, Cliente2 y Cliente3 ya fueron creados en el constructor ya podemos llamar a sus métodos como son los de Depositar y Extraer:
procedure TBanco.Operar; begin Cliente1.Depositar(100); Cliente2.Depositar(300); Cliente3.Depositar(400); Cliente1.Extraer(50); end;
Lo mismo en el método DepositosTotales podemos imprimir lo que tiene cada cliente en su cuenta y sumar dichos montos:
procedure TBanco.DepositosTotales;
var
suma: Double;
begin
suma := Cliente1.Monto + Cliente2.Monto + Cliente3.Monto;
Cliente1.Imprimir;
Cliente2.Imprimir;
Cliente3.Imprimir;
WriteLn('El banco tiene un total de ', suma:0:2);
end;
Finalmente el destructor tiene por objetivo eliminar el espacio en memoria ocupado por los campos Cliente1, Cliente2 y Cliente3:
destructor TBanco.Destroy; begin Cliente1.Free; Cliente2.Free; Cliente3.Free; inherited Destroy; end;
Algo importante es que el destructor Destroy ya existe en la clase padre TObject y nosotros la debemos sobreescribir, para ello cuando la declaramos añadimos el modificador override:
destructor Destroy; Override;
En el bloque principal solo definimos un objeto de la clase Banco (no definimos objetos de la clase Cliente ya que los clientes son campos definidos dentro de la clase TBanco):
var Banco1: TBanco;
En el bloque principal creamos el objeto Banco1 llamando al constructor Create que es el que creamos nosotros en la clase TBanco:
begin Banco1 := TBanco.Create;
Luego llamamos a los métodos Operar y DepositosTotales:
Banco1.Operar; Banco1.DepositosTotales;
Finalmente debemos liberar el espacio ocupado por el objeto Banco1 llamando al método Free. El método Free se encarga de llamar al método Destroy que creamos nosotros en la clase TBanco:
Banco1.Free; ReadLn; end.
Plantear un programa que permita jugar a los dados. Las reglas de juego son: se tiran tres dados si los tres salen con el mismo valor mostrar un mensaje que "gano", sino "perdió".
Lo primero que hacemos es identificar las clases:
Podemos identificar la clase TDado y la clase TJuegoDeDados.
Luego los campos y los métodos de cada clase:
TDado
campo
Valor
métodos
Tirar
Imprimir
TJuegoDeDados
campos
3 TDado (3 objetos de la clase TDado)
métodos
constructor
jugar
destructor
program Proyecto136;
{$APPTYPE CONSOLE}
type
TDado = class
Valor: Integer;
procedure Tirar;
procedure Imprimir;
end;
TJuegoDeDados = class
Dado1: TDado;
Dado2: TDado;
Dado3: TDado;
constructor Create;
destructor Destroy; Override;
procedure Jugar;
end;
procedure TDado.Tirar;
begin
Valor := Random(6) + 1;
end;
procedure TDado.Imprimir;
begin
WriteLn('Valor del dado:', Valor);
end;
constructor TJuegoDeDados.Create;
begin
inherited Create;
Dado1 := TDado.Create;
Dado2 := TDado.Create;
Dado3 := TDado.Create;
end;
destructor TJuegoDeDados.Destroy;
begin
Dado1.Free;
Dado2.Free;
Dado3.Free;
inherited Destroy;
end;
procedure TJuegoDeDados.Jugar;
begin
Dado1.Tirar;
Dado1.Imprimir;
Dado2.Tirar;
Dado2.Imprimir;
Dado3.Tirar;
Dado3.Imprimir;
if (Dado1.Valor = Dado2.Valor) and (Dado1.Valor = Dado3.Valor) then
WriteLn('Ganó')
else
WriteLn('Perdió');
end;
var
JuegoDeDados1: TJuegoDeDados;
begin
Randomize;
JuegoDeDados1 := TJuegoDeDados.Create;
JuegoDeDados1.Jugar;
JuegoDeDados1.Free;
ReadLn;
end.
La clase TDado define el campo Valor y dos métodos:
TDado = class
Valor: Integer;
procedure Tirar;
procedure Imprimir;
end;
El método Tirar genera un valor aleatorio comprendido entre 1 y 6:
procedure TDado.Tirar; begin Valor := Random(6) + 1; end;
El método Imprimir muestra el valor aleatorio generado en el otro método:
procedure TDado.Imprimir;
begin
WriteLn('Valor del dado:', Valor);
end;
La clase TJuegoDeDados define tres campos de tipo TDado, esto hace que tengamos que declarar los métodos Create (donde creamos los tres dados) y el método Destroy (donde liberamos el espacio reservado para los tres objetos):
TJuegoDeDados = class
Dado1: TDado;
Dado2: TDado;
Dado3: TDado;
constructor Create;
destructor Destroy; Override;
procedure Jugar;
end;
En el constructor Create, primero llamamos al Create de la clase padre y luego creamos los tres objetos de la clase TDado:
constructor TJuegoDeDados.Create; begin inherited Create; Dado1 := TDado.Create; Dado2 := TDado.Create; Dado3 := TDado.Create; end;
En el destructor llamamos al Free de cada objeto y luego llamamos al Destroy de la clase padre:
destructor TJuegoDeDados.Destroy; begin Dado1.Free; Dado2.Free; Dado3.Free; inherited Destroy; end;
El método Jugar tira los tres dados y verifica si tienen el mismo valor:
procedure TJuegoDeDados.jugar;
begin
Dado1.Tirar;
Dado1.Imprimir;
Dado2.Tirar;
Dado2.Imprimir;
Dado3.Tirar;
Dado3.Imprimir;
if (Dado1.Valor = Dado2.Valor) and (Dado1.Valor = Dado3.Valor) then
WriteLn('Ganó')
else
WriteLn('Perdió');
end;
En le bloque principal de nuestro programa definimos un objeto de la clase TJuegoDeDados y llamamos a sus métodos:
var JuegoDeDados1: TJuegoDeDados; begin Randomize; JuegoDeDados1 := TJuegoDeDados.Create; JuegoDeDados1.Jugar; JuegoDeDados1.Free; ReadLn; end.
program Proyecto137;
{$APPTYPE CONSOLE}
type
TSocio = class
Nombre: String;
Antiguedad: Integer;
constructor Create;
procedure Imprimir;
end;
TClub = class
Socio1: TSocio;
Socio2: TSocio;
Socio3: TSocio;
constructor Create;
destructor Destroy; override;
procedure MasAntiguedad;
end;
constructor TSocio.Create;
begin
Write('Ingrese el nombre del socio:');
ReadLn(Nombre);
Write('Ingrese la antiguedad:');
ReadLn(Antiguedad);
end;
procedure TSocio.Imprimir;
begin
WriteLn('Socio ', Nombre, ' tiene una antiguedad de ', Antiguedad);
end;
constructor TClub.Create;
begin
inherited Create;
Socio1 := TSocio.Create;
Socio2 := TSocio.Create;
Socio3 := TSocio.Create;
end;
destructor TClub.Destroy;
begin
Socio1.Free;
Socio2.Free;
Socio3.Free;
inherited Destroy;
end;
procedure TClub.MasAntiguedad;
begin
Socio1.Imprimir;
Socio2.Imprimir;
Socio3.Imprimir;
WriteLn('Socio más antiguo en el club');
if (Socio1.Antiguedad > Socio2.Antiguedad) and (Socio1.Antiguedad > Socio3.Antiguedad) then
Socio1.Imprimir
else
if Socio2.Antiguedad > Socio3.Antiguedad then
Socio2.Imprimir
else
Socio3.Imprimir;
end;
var
Club1: TClub;
begin
Club1 := TClub.Create;
Club1.MasAntiguedad;
Club1.Free;
ReadLn;
end.