我正在开发一个项目,我有一个像这样的接口TRectangle:
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;
procedure SetColor(const aColor: integer);
function GetColor: integer;
property Color: integer read GetColor write SetColor;
protected
{$IFNDEF AUTOREFCOUNT}
[Volatile] FRefCount: Integer;
{$ENDIF}
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
end;
_AddRef
和_Release
与InterfacedObject
中的相同:
function TGameRectangle._AddRef: Integer;
begin
{$IFNDEF AUTOREFCOUNT}
Result := AtomicIncrement(FRefCount);
{$ELSE}
Result := __ObjAddRef;
{$ENDIF}
end;
function TGameRectangle._Release: Integer;
begin
{$IFNDEF AUTOREFCOUNT}
Result := AtomicDecrement(FRefCount);
if Result = 0 then
Destroy;
{$ELSE}
Result := __ObjRelease;
{$ENDIF}
end;
要创建矩形,请执行以下操作:
var
lRect: TGameRectangle;
begin
lRect := TGameRectangle.Create(self);
lRect.Parent := Layout1;
lRect.Align := TAlignLayout.alClient;
FIntObj := lRect as IBoardShape;
稍后我将FIntObj
设置为nil
即可将其释放。在Windows上,当我按照_Release
时,引用计数为1,计数减少并且对象被释放。当我在Android上运行时,当我进入_Release
时引用计数为5(引用计数显示在__ObjRelease
内)。由于引用计数仍然很高,因此对象不会释放。
我在一个非常简单的演示中重新创建了这个,基本上只使用了我在这里发布的代码。有人可以解释ARC的不同之处是导致引用计数如此之高吗?
答案 0 :(得分:1)
所有这些在ARC下都是不必要的,因为ARC已经计算了引用并控制了生命周期。
在ARC下,您可以而且应该依赖基类中的IInterface
实现。
在ARC下,您的代码应如下所示:
TGameRectangle = class(TRectangle, IBoardShape)
private
FColor: integer;
procedure SetColor(const aColor: integer);
function GetColor: integer;
property Color: integer read GetColor write SetColor;
end;
更大的问题是您的代码永远无法在非ARC平台上运行。那是因为你拥有一个TComponent
后代。因此,所有者拥有对矩形对象的引用,并将在它被销毁时尝试销毁。除此之外,您的接口引用计数也取决于所有权。通常,对象需要只有一个所有者。你的设计给了他们两个。
如果对象没有所有者,您应该在非ARC平台上仅通过接口引用计数来管理生命周期。我在answer的前一个问题中详细讨论了这个问题。