我知道接口对象是引用计数,因此无需手动释放它。但是如果它有一个TObject继承成员,我应该在析构函数中手动释放这个成员吗?
请考虑以下代码:
program Project2;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Classes;
type
ITestInterface = interface(IInvokable)
['{A7BDD122-7DC6-4F23-93A2-B686571AB2C8}']
procedure TestMethod;
end;
TTestObj = class(TInterfacedObject, ITestInterface)
constructor Create;
destructor Destroy; override;
private
FData: TStrings;
public
procedure TestMethod;
end;
{ TTestObj }
constructor TTestObj.Create;
begin
FData := TStringList.Create;
end;
destructor TTestObj.Destroy;
begin
Writeln('Destroy'); // This line won't apear in the console ouput as the destructor won't be called.
FData.Free; // Who guarantees this member will be freed ?
inherited;
end;
procedure TTestObj.TestMethod;
begin
Writeln('TestMethod');
end;
{ Main }
procedure Main;
var
TestObj: TTestObj;
begin
TestObj := TTestObj.Create;
TestObj.TestMethod;
TestObj := nil; // TestObj should be freed at this moment ?
end;
begin
Writeln('Program start!');
Main;
Writeln('Program end.');
Readln;
end.
节目输出:
Program start!
TestMethod
Program end.
这意味着没有调用构造函数,并且成员FData
没有被释放?
我该怎么办?提前谢谢。
答案 0 :(得分:4)
您必须像往常一样释放析构函数中的TStrings
(除非您使用ARC编译器)。
父对象(TTestObject
)会自动释放 - 但仅当它用作接口 - 时,而不是它引用的对象,如FData
。
您正在使用该对象作为对象,但您必须将其用作接口以获取自动引用计数:
var
TestObj: ITestInterface;
但是TTestObject
是否实现了接口是无关紧要的,你必须总是释放析构函数中的任何聚合对象。
同样,只有当您使用的编译器没有为对象实现ARC时(例如,如果您的目标是Win32,Win64,macOS),上述情况才会成立。