Delphi接口引用计数机制

时间:2017-07-18 20:58:19

标签: delphi

确实网上有很多关于此的内容,但更多的是我读起来更加困惑。我编写了一个名为Combinatorics的组件来做一些数学概率的东西。代码非常简短,因为我不希望它变得复杂。我在这里做一点预览:

//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;

您不需要了解功能和程序的实施方式,这对问题并不重要(您可以轻松想象他们的工作)。

这是我的第一个组件,我编译并安装它并且它可以工作。但是我无法理解。

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.

查看Update;程序。我创建了这个,因为当用户放弃组件(link)的形式时,他必须在对象检查器中设置(或使用代码在某处),构造函数中需要3个重要参数。

FEngine: ICombinatorio我可以为它分配一个类(TCombinazioni,TDisposizioni或TPermutazioni)而不用最后尝试,因为有引用计数机制。我不确定我是否已正确编码。假设:

  1. 用户选择cDisposition并进行计算
  2. 用户选择cDisposition(不同的值)并进行计算
  3. 用户选择cPermutation并进行计算
  4. 我一直致力于FEngine。引用计数如何变为零?当形式(和组件)破坏时它会变为零吗?我希望我已经很好地解释了我不理解的东西。 FEngine是一个私有变量,我在运行时向它求助不同的类(调用Create)。当表单销毁或分配新类时,引用计数是否为0?

    我的编码就像上面那样,因为尼克霍奇在他的书中做到了这一点,我当然相信他,但我想知道我做了什么。

1 个答案:

答案 0 :(得分:8)

根据可以看到的代码,第一次调用Update时,会创建ICombinatorio的新实现者并将其分配给FEngine;引用计数将为1.在Update被调用的以下时间,将创建ICombinatorio实现者​​的另一个新实例(其引用计数将为1)并分配给FEngineFEngine指向的先前实现者实例将使其引用计数递减;如果它为零,那么它将被销毁。 (它可能基于您的代码示例)。

此外,当调用组件的析构函数时(当拥有的Form被销毁时),隐式实例清理代码会将FEngine设置为nil,这将减少引用计数(并且,基于你的样本,将被销毁。)

因此,根据您的代码示例,我希望您的代码能够正常运行;干净地实现和销毁ICombinatorio接口对象。