阅读专家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之间的分离。
答案 0 :(得分:15)
TDataModule
是TComponent
后代,TComponent
实现IInterface
及相关的引用计数方法
TComponent = class(TPersistent, IInterface, IInterfaceComponentReference)
但是,TComponent
禁用了引用计数,并且可以手动或通过非ARC编译器上的所有权模型管理组件。
更准确地说,TComponent
已禁用引用计数,除非它用作Windows COM对象的包装器。这不是这种情况。
在ARC编译器上,手动管理存在轻微的复杂性 - 实际上是自动管理,因为如果您不允许TComponent
后代通过所有权进行管理,则必须使用DisposeOf
来释放它们
TComponent
行为与TInterfacedObject
行为不同。
在上面的情况下,没有泄漏,因为Application
拥有该数据模块,它将在所有编译器上适当地管理数据模块的生命周期。
try... finally
阻止不是用于内存管理,而是用于保护BeginUpdate... EndUpdate
您必须在所有编译器上保留try...finally
。