Подтвердить что ты не робот

Механизм подсчета ссылок интерфейса 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;. Я создал это, потому что, когда пользователь удаляет компонент (ссылка) в форме, которую он должен установить в инспекторе объектов (или с кодом где-то ) 3 важных параметра, необходимых в конструкторе.

Так как FEngine: ICombinatorio, я могу назначить ему класс (TCombinazioni, TDisposizioni или TPermutazioni) без попытки, потому что есть механизм подсчета ссылок. Я не уверен, правильно ли я это закодировал. Предположим, что:

  • Пользователь выбирает cDisposition и выполняет расчет
  • Пользователь выбирает cDisposition (разные значения) и выполняет расчет
  • Пользователь выбирает cPermutation и выполняет расчет

Я всегда работаю над FEngine. Как счетчик возвращается к нулю? Опустится ли оно до нуля, когда форма (и компонент) разрушается? Надеюсь, я хорошо объяснил, чего не понимаю. FEngine является частной переменной, и я полагаю, что он во время выполнения использует разные классы (вызывает Create). Возвращает ли значение ref значение 0, когда форма уничтожается или когда назначен новый класс?

Я закодировал его, как описано выше, потому что nick hodges сделал это в своей книге, и я ему доверяю, конечно, но я хотел бы знать, что я делаю.

4b9b3361

Ответ 1

На основе кода, который можно увидеть, при первом вызове Update создается новый конструктор ICombinatorio и назначается FEngine; счетчик ссылок будет равен 1. Следующие вызовы, которые Update вызывается, будет создан новый новый экземпляр конструктора ICombinatorio (его счетчик ссылок будет равен 1) и присваивается FEngine. Предыдущий экземпляр-исполнитель, на который указывает FEngine, будет иметь счетчик ссылок, декрементированный; если он равен нулю, то он будет уничтожен. (Вероятно, это будет основано на вашем примере кода).

Кроме того, когда вызывается деструктор компонента (когда собственная форма уничтожается), неявный код очистки экземпляра будет устанавливать FEngine на nil, что уменьшит счетчик ссылок (и, основываясь на вашем примере, будет уничтожен).

Итак, основываясь на вашем примере кода, я ожидаю, что ваш код будет работать правильно; чисто инстанцирование и уничтожение сопряженных объектов ICombinatorio.