Интерфейс Delphi не учитывает ссылки

Читая книгу Expert Delphi, я нашел кое-что, чего не могу понять. Автор создал блок с таким кодом:

 IToDoData = interface //CRUD
    function ToDoCreate(aValue: TToDo): integer;
    function ToDoRead(id: integer; out aValue: TToDo): boolean;
    function ToDoUpdate(aValue: TToDo): boolean;
    function ToDoDelete(id: integer): boolean;
    procedure ToDoList(aList: TToDos);
  end;

Затем он решил использовать DataModule и реализовать описанный выше интерфейс следующим образом:

type
  TDMToDo = class(TDataModule, IToDoData)
    // ... other code ...
  public
    // IToDoData
    function ToDoCreate(aValue: TToDo): integer;
    function ToDoRead(id: integer; out aValue: TToDo): boolean;
    function ToDoUpdate(aValue: TToDo): boolean;
    function ToDoDelete(id: integer): boolean;
    procedure ToDoList(aList: TToDos);
  end;

Пока все хорошо, но обратите внимание, что он не поставил TInterfacedObject, поэтому здесь у нас нет таких методов, как AddRef и так далее. Я предполагаю, что приведенный выше код в порядке, но он должен быть включен в блок try... finally.

В основной форме (конечно, модуль модуля данных — это разделы использования) есть такая функция:

function TFormToDo.GetToDoData: IToDoData;
begin
  if DMToDo = nil then
    DMToDo := TDMToDo.Create(Application);
  Result := DMToDo;
end;

Приведенный выше код позволяет написать такой код:

begin
  GetToDoData.ToDoList(FToDos);

  ListView1.BeginUpdate;
  try
    //populate the list
  finally
    ListView1.EndUpdate;
  end;
end;

Не вызывает ли это утечку памяти? По крайней мере на окнах. Я новичок в delphi, поэтому я могу потерпеть неудачу, но я читал в Интернете, что Android и IOs имеют ARC, поэтому не нужно беспокоиться о попытке, наконец.

В Windows НЕТ ARC, поэтому я должен использовать попытку .. наконец, если нет такой реализации, как TInterfacedObject (здесь ее нет). Так это ошибка?


Приложение представляет собой приложение ToDo, в котором вы пишете/читаете/сохраняете свои заметки. Модуль данных имеет компоненты доступа FireDAC, а методы интерфейса используются для доступа к db. Это сделано для того, чтобы сохранить разделение между пользовательским интерфейсом и базой данных.


person Emma Rossignoli    schedule 13.08.2017    source источник
comment
Будет. Что еще сказать, в Мадриде ужасная погода :)   -  person Victoria    schedule 13.08.2017
comment
@Victoria, к сожалению, тоже самое ;)   -  person Emma Rossignoli    schedule 13.08.2017


Ответы (1)


TDataModule является потомком TComponent, а TComponent реализует IInterface и связанные с ним методы подсчета ссылок.

  TComponent = class(TPersistent, IInterface, IInterfaceComponentReference)

Однако в TComponent подсчет ссылок отключен, и компоненты управляются либо вручную, либо через модель владения на компиляторе, отличном от ARC.

Чтобы быть более точным, TComponent отключил подсчет ссылок, если только он не служит оболочкой для COM-объекта Windows. Что не так здесь.

В компиляторе ARC есть небольшая сложность с ручным управлением - на самом деле автоматическое управление, потому что, если вы не разрешаете TComponent потомкам управлять через владение, они должны быть выпущены с DisposeOf.

Поведение TComponent отличается от поведения TInterfacedObject в отношении подсчета ссылок в классическом компиляторе.

В приведенном выше случае утечки нет, потому что Application владеет этим модулем данных, и он будет соответствующим образом управлять временем жизни модуля данных на всех компиляторах.


Блок try... finally нужен не для управления памятью, а для защиты BeginUpdate... EndUpdate Вы должны оставить try...finally на всех компиляторах.

person Dalija Prasnikar    schedule 13.08.2017
comment
Так что добавление TInterfacedObject было бы ошибкой или просто чем-то дополнительным? - person Emma Rossignoli; 13.08.2017
comment
Куда бы вы поместили TInterfacedObject? Вы можете наследовать только от одного класса, и это TDataModule здесь. - person Dalija Prasnikar; 13.08.2017
comment
Хорошо, спасибо :), так что модуль данных уже дает мне то, что мне нужно, чтобы быть уверенным, что он будет подсчитан. - person Emma Rossignoli; 13.08.2017
comment
Он не будет учитываться в компиляторе, отличном от ARC. TComponent отключает подсчет ссылок. Его поведение отличается от поведения TInterfacedObject. - person Dalija Prasnikar; 13.08.2017