Delphi接口未引用计数

时间:2017-08-13 19:47:43

标签: delphi delphi-10.2-tokyo

阅读专家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块中。

在主窗体中(数据模块单元当然是uses子句),有这样的函数:

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和IO有ARC,所以不用担心最后尝试。

Windows没有ARC所以我必须使用try .. finally,除非有像TInterfacedObject这样的实现(这里没有' t)。这是一个错误吗?

该应用程序是一个ToDo应用程序,您可以在其中编写/读取/保存您的笔记。数据模块具有FireDAC访问组件,接口方法用于访问db。这是为了保持UI和db之间的分离。

1 个答案:

答案 0 :(得分:15)

TDataModuleTComponent后代,TComponent实现IInterface及相关的引用计数方法

  TComponent = class(TPersistent, IInterface, IInterfaceComponentReference)

但是,TComponent禁用了引用计数,并且可以手动或通过非ARC编译器上的所有权模型管理组件。

更准确地说,TComponent已禁用引用计数,除非它用作Windows COM对象的包装器。这不是这种情况。

在ARC编译器上,手动管理存在轻微的复杂性 - 实际上是自动管理,因为如果您不允许TComponent后代通过所有权进行管理,则必须使用DisposeOf来释放它们

对于经典编译器上的引用计数,

TComponent行为与TInterfacedObject行为不同。

在上面的情况下,没有泄漏,因为Application拥有该数据模块,它将在所有编译器上适当地管理数据模块的生命周期。

try... finally阻止不是用于内存管理,而是用于保护BeginUpdate... EndUpdate您必须在所有编译器上保留try...finally