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.