SITUATION
I am studying Delphi from Marco Cantu's book and I already have experience with OOP because I usually work with Java and PHP. To better understand what I'm reading I've made this test:
type
TFraction = class
private
number: double;
num, den: integer;
fraction: string;
function hcf(x: integer; y: integer): integer;
public
constructor Create(numerator: integer; denominator: integer); overload;
constructor Create(value: string); overload;
function getFraction: string;
end;
This is a super easy class that converts a decimal number into a fraction. I'm not including the other parts of the code where I define constructors and functions since they aren't useful for my question. I am creating the object in this way.
var a: TFraction;
begin
a := TFraction.Create(225, 35);
ShowMessage(a.getFraction);
//The output of ^ is 45/7
a.Free;
end;
QUESTION
From what I've learnt, I know that I have to get rid of the object once I've used it and in fact I am using the Free
. In this way I free the memory and I avoid memory leaks.
By the way I see that I also have the possibility to override a destructor
. I don't understand very well the behavior of the Free
and the Destroy
. I use the Free
when I have to get rid of an object that I don't need anymore. When I override a destructor I can free the object and also make other actions?
In short, when is it good to use the Free? And when should I prefer the Destroy?
In general, the destructor is used if you need to do something during object destruction which otherwise wouldn't be done automatically. Like freeing memory that you initialize in the constructor. In your example, there is no need to override the destructor, since (presumably) you don't create anything which needs to be destroyed manually.
Also, keep in mind that Destroy
is not intended to be called by you at all - neither internally or externally. Free
automatically takes care of calling that for you - with a little extra work going on. Free
checks if the object is nil
or not, and only calls Destroy
if it's not nil
.
Take this for example:
type
TMyObject = class(TObject)
private
FSomeOtherObject: TSomeOtherObject;
public
constructor Create;
destructor Destroy; override;
end;
constructor TMyObject.Create;
begin
inherited;
FSomeOtherObject:= TSomeOtherObject.Create;
end;
destructor TMyObject.Destroy;
begin
FSomeOtherObject.Free;
inherited;
end;
Just as an added note, the usage I see above is missing something. What if the code between Create
and Free
raises some exception? The procedure would exit, and it would never be free'd. So instead, you should use a try / finally
block...
a := TFraction.Create(225, 35);
try
ShowMessage(a.getFraction);
finally
a.Free;
end;
This would ensure that no matter what happens between try
and finally
, the code between finally
and end
will always be called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With