2017-07-18 105 views
10

事实上,网上有很多关于此的东西,但更多的是我读了更多的混淆我。我写了一个名为Combinatorics的组件,它执行一些数学概率的东西。代码非常简短,因为我不想让它变得复杂。我在这里做一个小的预览:Delphi界面引用计数机制

//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因为有ref计数机制,所以我可以最终没有尝试地给它赋一个类(TCombinazioni,TDisposizioni或TPermutazioni)。我不确定我是否已正确编码。假设:

  1. 用户选择cDisposition和做了计算
  2. 用户选择cDisposition(不同的值),并做了计算
  3. 用户选择cPermutation和做了计算

我我总是在FEngine上工作。参考计数如何归零?当表单(和组件)销毁时它是否为零?我希望我已经解释了我不明白的东西。 FEngine是一个私有变量,我在运行时为它分配不同的类(调用Create)。当表格破坏或分配新类时,ref计数是否为0?

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

+0

您可以简单地将析构函数添加到您的接口对象中,并将断点放在发现的位置。 –

+1

我猜你指的是“在delphi中编码”的TEncryption示例;)我刚刚检查过这本书,你应该在本章中间找到关于TInterfacedObject的问题的答案! –

+0

@Sertac我不知道你在说什么对不起,我现在在学习,所以我觉得这很容易问 –

回答

8

根据可以看到的代码,第一次调用Update时,会创建一个ICombinatorio的新实现器并将其指定给FEngine;引用计数将为1.在调用Update后,将创建另一个ICombinatorio实现器实例的新实例(其引用计数为1)并分配给FEngineFEngine指向的前一个实现者实例将使其引用计数递减;如果它是零,那么它将被销毁。 (它可能会基于你的代码示例)。另外,当调用组件的析构函数时(当拥有窗体被销毁时),隐式实例清理代码将把FEngine设置为零,这将减少引用计数(并根据您的示例,将被销毁)。

因此,根据您的代码示例,我希望您的代码能正常工作;干净地instanciating和销毁接口对象ICombinatorio

+0

Aaaaah ok,所以当我抨击FEngine一个新的实例时,旧的实例的ref为0(所以它被销毁了)并且新的实例化为1.我认为参考没有去0但有一个总数。你说它是0-1-0-1-0-1 ......但我认为它就像0-1-2-3-4,然后是0(最后是毁灭)。谢谢 –

+1

是的,这是正确的。 –

+0

Super Dave谢谢 –