我是接口的新手,并且已经在我的最新项目中尝试了它们。我有这个(简化的)界面:
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,但听起来并不合适。 (我尝试了它并且它可以工作,但它会导致其他问题 - 尝试释放接口时Delphi代码中的错误。)
我不确定的一件事:由于我的TGameRectangle
并非来自TInterfacedObject
,我应该自己做引用计数吗?或者我误解了TInterfacedObject
的用途是什么?
答案 0 :(得分:1)
我将限制我对没有ARC的桌面平台的回答。那是因为在ARC平台上无所事事。 ARC框架将为您管理生命周期,您不得重新实施_AddRef
和_Release
。
对于非ARC平台,您有一个基本的设计问题。您希望对象的生命周期由两个独立的机制控制:
TComponent
所有者和你需要下定决心以某种方式做到这一点。但不是两个。
如果您选择第一个选项,则只需确保在销毁所有者之前清除界面参考。然后让所有者破坏你的矩形对象。
如果您选择第二个选项,则需要将nil
作为构造函数的owner参数传递。然后按照TInterfacedObject
实现接口引用计数生命周期管理。
一种常见的模式是让传递给构造函数的所有者的值确定生命周期模型。因此,当所有者为nil
时,界面引用计数控制生命。否则所有者控制它。这种模式的典型示例是TXMLDocument
。
所有这一切,我不认为这种模式适用于可视组件。该框架的设计使得可视化组件的生命周期不受接口引用计数的控制。我认为反对那种设计是愚蠢的。我建议你选择选项1.
答案 1 :(得分:0)
是的,如果要使用接口和引用计数,则需要从提供引用计数的类型继承,或者提供自己的_AddRef
和_Release
实现。
您的TGameRectangle所做的_AddRef
和_Release
有什么作用?