我是接口(interface)的新手,并且一直在我的最新项目中尝试它们。我有这个(简化的)界面:
IBoardShape = interface(IInterface)
function GetColor: integer;
procedure SetColor(const aColor: integer);
property Color: integer read GetColor write SetColor;
end;
几个类是这样的:
TGameRectangle = class(TRectangle, IBoardShape)
private
FColor: integer;
function GetColor: integer;
procedure SetColor(const aColor: integer);
property Color: integer read GetColor write SetColor;
end;
我有一个在自己的数据模块中创建形状的工厂。
function TdmShapeManager.CreateRect(aParent: TLayout): IBoardShape;
var
lRect: TGameRectangle;
begin
lRect := TGameRectangle.Create(self);
lRect.Parent := aParent;
lRect.Align := TAlignLayout.alClient;
result := lRect as IBoardShape;
end;
结果被添加到
TList<IBoardShape>
.所有这些都运行良好,直到我开始尝试在运行时删除形状。我发现
TList[I] := nil
没有释放项目,控件只会停留在屏幕上。所以,从这里我不确定。我发现我可以将对象转换为 TShape 并在其上调用 .Free,但这听起来不对。 (我尝试过它并且它可以工作,但它会导致其他问题 - 尝试释放接口(interface)时 Delphi 代码中的错误。)我不确定的一件事:自从我的
TGameRectangle
不来自 TInterfacedObject
,我应该自己做引用计数吗?还是我误解了什么TInterfacedObject
是为了?
最佳答案
我将把我的答案限制在没有 ARC 的桌面平台上。那是因为在 ARC 平台上无事可做。 ARC 框架将为您管理生命周期,您不得重新实现 _AddRef
和 _Release
.
对于非 ARC 平台,您有一个基本的设计问题。您希望对象的生命周期由两种独立的机制控制:
TComponent
所有者和 您需要下定决心以一种或另一种方式做到这一点。但不是两者兼而有之。
如果您选择第一个选项,您只需要确保在销毁所有者之前清除接口(interface)引用。然后让所有者销毁您的矩形对象。
如果您选择第二个选项,您需要通过
nil
作为构造函数的所有者参数。然后按照TInterfacedObject
实现接口(interface)引用计数生命周期管理.一个常见的模式是让传递给构造函数的所有者的值决定生命周期模型。所以,当所有者是
nil
,接口(interface)引用计数控制生命。否则所有者控制它。这种模式的典型例子是 TXMLDocument
.尽管如此,我认为这种模式不适用于视觉组件。该框架的设计使得可视组件的生命周期不受接口(interface)引用计数的控制。我认为反对这种设计是愚蠢的。我建议你选择选项 1。
关于delphi - 释放从 Rectangle 继承的接口(interface)对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21770260/