Indeed there is a lot of stuff online about this but more I read more confuse I am. I have written a component called Combinatorics
that does some math probability stuff. The code is pretty short and easy because I don't want it to be complicated. I am doing a little preview here:
//Combinatorio.pas
type
ICombinatorio = interface
function getSoluzioni(): integer; //soluzioni means "Solutions"
function getFormula(): string;
end;
//ImplCombinatorio.pas
type
TCombinazioni = class(TInterfacedObject, ICombinatorio)
private
n, k: integer;
ripetizione: boolean;
function fattoriale(const x: integer): integer;
public
constructor Create(const n, k: integer; const ripetizione: boolean);
function getSoluzioni(): integer;
function getFormula(): string;
end;
TDisposizioni = class(TInterfacedObject, ICombinatorio)
private
n, k: integer;
ripetizione: boolean;
function fattoriale(const x: integer): integer;
public
constructor Create(const n, k: integer; const ripetizione: boolean);
function getSoluzioni(): integer;
function getFormula(): string;
end;
TPermutazioni = class(TInterfacedObject, ICombinatorio)
private
n: integer;
k: string;
ripetizione: boolean;
function fattoriale(const x: integer): integer;
public
constructor Create(const n: integer; const k: string; ripetizione: boolean);
function getSoluzioni(): integer;
function getFormula(): string;
end;
You don't need to see how functions and procedures are implemented, it's not important for the question (and you can easily imagine what they do).
This is my first component ever, I have compiled and installed it and it works. However I cannot understand something.
unit TCombinatorio;
interface
uses
System.SysUtils, System.Classes, Combinatorio, ImplCombinatorio;
type
cCombinatorio = (cNull = 0, cDisposition = 1, cPermutation = 2, cCombination = 3);
type
TCombinatorics = class(TComponent)
strict private
{ Private declarations }
Fn, Fk: integer;
FRep: boolean;
FType: cCombinatorio;
FEngine: ICombinatorio;
procedure Update;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
function getSolution: integer;
function getFormula: string;
published
property n: integer read Fn write Fn;
property k: integer read Fk write Fk;
property kind: cCombinatorio read FType write FType default cNull;
property repetitions: boolean read FRep write FRep;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('RaffaeleComponents', [TCombinatorics]);
end;
{ TCombinatorics }
constructor TCombinatorics.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Fn := 0;
Fk := 0;
FType := cNull;
repetitions := false;
end;
function TCombinatorics.getFormula: string;
begin
Update;
Result := FEngine.getFormula;
end;
function TCombinatorics.getSolution: integer;
begin
Update;
Result := FEngine.getSoluzioni;
end;
procedure TCombinatorics.Update;
begin
case FType of
cDisposition:
FEngine := TDisposizioni.Create(n, k, repetitions);
cPermutation:
FEngine := TPermutazioni.Create(n, '', repetitions);
cCombination:
FEngine := TCombinazioni.Create(n, k, repetitions);
cNull:
raise Exception.Create('You have to select a type.');
end;
end;
end.
Look at the Update;
procedure. I have created that because when the user drops the component ( link ) in the form he has to setup in the object inspector (or with the code somewhere) 3 important parameters required in the constructor.
Since FEngine: ICombinatorio
I can assign to it a class (TCombinazioni, TDisposizioni or TPermutazioni) without try finally because there is the ref count mechanism. I am not sure if I have coded this properly. Suppose that:
cDisposition
and does a calculationcDisposition
(different values) and does a calculationcPermutation
and does a calculationI am always working on the FEngine
. How does the ref count go to zero? Does it go to zero when the form (and the component) destroys? I hope I have explained well what I don't understand. The FEngine
is a private variable and I assing to it at runtime different classes (calling the Create). Does the ref count go to 0 when the form destroys or when a new class is assigned?
I coded it like above because nick hodges did that in his book and I trust him of course but I'd like to know what I do.
Based on the code that can be seen, the first time Update
is called, a new implementor of ICombinatorio
is created and assigned to FEngine
; the reference count will be 1. The following times that Update
is called, another new instance of ICombinatorio
implementor will be created (its reference count will be 1) and is assigned to FEngine
. The previous implementor instance that FEngine
pointed to will have its reference count decremented; if it is zero, then it will be destroyed. (It probably will be based on your code sample).
Also, when the destructor of the component is called (when the owning Form is destroyed), the implicit instance clean-up code will set FEngine
to nil, which will decrement the reference count (and, based on your sample, will be destroyed).
So, based on your code sample, I would expect your code will work properly; cleanly instanciating and destroying the ICombinatorio
interfaced objects.
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