释放从 Rectangle 派生的接口对象

2024-01-24

我对界面很陌生,并且一直在我最新的项目中尝试它们。我有这个(简化的)界面:

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 is for?


我将把我的答案限制在没有 ARC 的桌面平台上。那是因为在 ARC 平台上没有什么可做的。 ARC 框架将为您管理生命周期,您不得重新实现_AddRef and _Release.

对于非 ARC 平台,您会遇到一个基本的设计问题。您希望对象的生命周期由两个独立的机制控制:

  1. The TComponent所有者,以及
  2. 接口引用计数。

你需要下定决心以一种或另一种方式去做。但不是两者兼而有之。

如果您选择第一个选项,您只需要确保在所有者被销毁之前清除接口引用。然后让主人销毁你的矩形对象。

如果您选择第二个选项,则需要通过nil作为构造函数的所有者参数。然后按照接口实现引用计数生命周期管理TInterfacedObject.

一种常见的模式是让传递给构造函数的所有者的值确定生命周期模型。所以,当主人nil,接口引用计数控制寿命。否则所有者控制它。这种模式的典型例子是TXMLDocument http://docwiki.embarcadero.com/Libraries/en/Xml.XMLDoc.TXMLDocument.

尽管如此,我认为这种模式不适用于视觉组件。该框架的设计使得视觉组件的生命周期不受接口引用计数的控制。我认为反对这种设计是愚蠢的。我建议你选择选项1。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

释放从 Rectangle 派生的接口对象 的相关文章

随机推荐