Delphi中的接口引用计数支持函数
我有THuman实现 interface 的类ICanTalk。
但是每当我尝试检查人类是否可以说话时,Supports函数都会破坏对象实例,尽管代码中有引用。
我误解了什么?
procedure TForm1.Button1Click(Sender: TObject);
var
Obj:TInterfacedObject;
begin
Obj:=THuman.Create('Great guy');
// if Supports(Obj, ICanTalk) then //Object destroyed here if uncommented
(Obj as ICanTalk).TalkTo(Memo1.Lines);
end;
执行
ICanTalk = interface
['{57E5EF90-EB11-421C-AAFB-18CD789C0956}']
procedure TalkTo(List:TStrings);
end;
THuman = class(TInterfacedObject, ICanTalk)
private
FName: string;
public
procedure TalkTo(List:TStrings);
property Name:string read FName;
constructor Create(const AName:string);
end;
constructor THuman.Create(const AName: string);
begin
FName:=AName;
end;
procedure THuman.TalkTo(List: TStrings);
begin
List.Add(Name+' says Hello World!');
end;
回答
这是预期的。当您阅读有关该Supports功能的文档时,您会发现:
警告
除了检查 TClass 是否实现接口的重载之外,所有其他版本的 Supports 都会从一个对象或另一个接口引用中提取一个接口引用,导致底层对象的引用计数增加,然后将在退出时释放接口(减少引用计数)。对于引用计数为零的对象,这将导致对象销毁。
var Obj: TInterfacedObject; begin Obj := TInterfacedObject.Create; if Supports(Obj, IInterface) then { ... at this point Obj will be freed } end;
你写了,
尽管在代码中引用(在可见区域)
不,没有参考。您声明Obj为TInterfacedObject(类实例变量——不是接口变量),因此没有引用计数。
如果您改为使用接口类型变量,它将使用引用计数:
var
Obj: IInterface;