2017-07-18 8 views
10

In der Tat gibt es eine Menge Sachen online zu diesem Thema, aber ich lese mehr verwirren, ich bin. Ich habe eine Komponente geschrieben, die Combinatorics genannt wird, die einige Mathewahrscheinlichkeitstests durchführt. Der Code ist ziemlich kurz und einfach, weil ich nicht möchte, dass es kompliziert ist. Ich mache eine kleine Vorschau hier:Delphi-Schnittstelle Referenz Zählmechanismus

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

Sie müssen nicht sehen, wie Funktionen und Verfahren umgesetzt werden, es ist nicht wichtig für die Frage (und man kann sich leicht vorstellen, was sie tun).


Dies ist meine erste Komponente überhaupt, ich habe es kompiliert und installiert und es funktioniert. Ich kann jedoch etwas nicht verstehen.

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. 

Blick auf die Update; Verfahren. Ich habe das erstellt, weil, wenn der Benutzer die Komponente (link) in der Form löscht, muss er im Objektinspektor (oder mit dem Code irgendwo) 3 wichtige Parameter im Konstruktor einrichten.

Seit FEngine: ICombinatorio kann ich ihm eine Klasse zuweisen (TCombinazioni, TDisposizioni oder TPermutazioni), ohne es zu versuchen, schließlich gibt es den ref count-Mechanismus. Ich bin mir nicht sicher, ob ich das richtig codiert habe. Nehmen wir an, dass:

  1. Der Benutzer wählt cDisposition und führt eine Berechnung
  2. Der Benutzer wählt cDisposition (verschiedene Werte) und führt eine Berechnung
  3. Der Benutzer wählt cPermutation und führt eine Berechnung

I arbeite immer an der FEngine. Wie geht der Refcount auf Null? Geht es auf Null, wenn das Formular (und die Komponente) zerstört? Ich hoffe, ich habe gut erklärt, was ich nicht verstehe. Die FEngine ist eine private Variable und ich gebe ihr zur Laufzeit verschiedene Klassen (Aufruf der Create). Geht der ref count auf 0, wenn das Formular zerstört oder wenn eine neue Klasse zugewiesen wird?

Ich habe es wie oben beschrieben, weil Nick Hodges das in seinem Buch getan hat und ich vertraue ihm natürlich, aber ich würde gerne wissen, was ich mache.

+0

Sie könnten einfach Destruktoren zu Ihren verbundenen Objekten hinzufügen und Haltepunkte setzen, um herauszufinden, was passiert. –

+1

Ich denke, Sie beziehen sich auf das TEncryption Beispiel von "Kodierung in Delphi";) Ich habe gerade das Buch überprüft, Sie sollten die Antwort auf Ihre Fragen in der Mitte des Kapitels finden, wenn er über TInterfacedObject spricht! –

+0

@Sertac Ich weiß nicht, worüber du redest Entschuldigung, ich lerne jetzt, also dachte ich, es war einfacher zu fragen –

Antwort

8

Basierend auf den Code, der das erste Mal Update genannt wird, wird man sehen kann, ein neues Implementierer von ICombinatorio erstellt und FEngine zugewiesen; Der Referenzzähler wird 1 sein. Die folgenden Male, dass Update aufgerufen wird, wird eine weitere neue Instanz von ICombinatorio Implementor erstellt (seine Referenzzahl wird 1 sein) und ist FEngine zugewiesen. Die vorherige Implementorinstanz, auf die FEngine gezeigt wird, wird auf ihren Referenzzähler dekrementiert; Wenn es Null ist, wird es zerstört. (Es wird wahrscheinlich auf Ihrem Codebeispiel basieren).

Wenn der Destruktor der Komponente aufgerufen wird (wenn das besitzende Formular zerstört wird), wird der implizite Instanzbereinigungscode FEngine auf null setzen, wodurch die Referenzzahl verringert wird (und basierend auf Ihrer Stichprobe wird zerstört werden).

Also, basierend auf Ihrem Code-Beispiel, würde ich erwarten, dass Ihr Code ordnungsgemäß funktioniert; sauberes Instanziieren und Zerstören der verbundenen Objekte ICombinatorio.

+0

Aaaaah ok, also, wenn ich Fengine eine neue Instanz zu assistieren die alte hat eine ref von 0 (so ist es zerstört) und die neue geht zu 1. Ich dachte, dass die Referenz ging nicht auf 0, sondern hat eine Gesamtsumme. Du sagst, dass es 0-1-0-1-0-1 ist ... aber ich dachte, dass es wie 0-1-2-3-4 und dann am Ende 0 war (auf destroy). Danke –

+1

Ja, das ist richtig. –

+0

Super Dave danke –

Verwandte Themen