gpt4 book ai didi

delphi - 接口(interface)委托(delegate)+重写

转载 作者:行者123 更新时间:2023-12-03 18:21:34 25 4
gpt4 key购买 nike

由于Delphi中缺乏多重继承,我需要使用接口(interface)委托(delegate)。这对我来说是一个非常新的主题,我在将重写与接口(interface)委托(delegate)结合起来时遇到了问题。

TMyNode 必须继承自 TBaseClass 并需要实现 IAddedStuff 。我希望在 TAddedStuffDefaultImplementation 中拥有 IAddedStuff 的所有函数的默认实现,因此我不需要到处都有重复的 getter/setter 代码。因此,我使用 DefaultBehavior 委托(delegate)了这些事情。

问题是, TAddedStuffDefaultImplementation 应该有虚拟方法,所以我想直接在 TMyNode 中重写它们。如果我写 FDefaultImplementation: TAddedStuffDefaultImplementation; 而不是 FDefaultImplementation: IAddedStuff; ,这确实有效。

但是现在,由于某些原因TAddedStuffDefaultImplementation会增加x: TBaseClass;的Ref-Counter,因此无法释放它。我该怎么办?

我的简化复制代码如下:

program Project2;

{$APPTYPE CONSOLE}

{$R *.res}

uses
System.SysUtils;

type
IAddedStuff = interface(IInterface)
['{9D5B00D0-E317-41A7-8CC7-3934DF785A39}']
function GetCaption: string; {virtual;}
end;

TAddedStuffDefaultImplementation = class(TInterfacedObject, IAddedStuff)
function GetCaption: string; virtual;
end;

TBaseClass = class(TInterfacedObject);

TMyNode = class(TBaseClass, IAddedStuff)
private
FDefaultImplementation: TAddedStuffDefaultImplementation;
public
property DefaultBehavior: TAddedStuffDefaultImplementation read FDefaultImplementation
write FDefaultImplementation implements IAddedStuff;
destructor Destroy; override;

// -- IAddedStuff
// Here are some functions which I want to "override" in TMyNode.
// All functions not declared here, should be taken from FDefaultImplementation .
function GetCaption: string; {override;}
end;

{ TAddedStuffDefaultImplementation }

function TAddedStuffDefaultImplementation.GetCaption: string;
begin
result := 'PROBLEM: CAPTION NOT OVERRIDDEN';
end;

{ TMyNode }

destructor TMyNode.Destroy;
begin
if Assigned(FDefaultImplementation) then
begin
FDefaultImplementation.Free;
FDefaultImplementation := nil;
end;

inherited;
end;

function TMyNode.GetCaption: string;
begin
Result := 'OK: Caption overridden';
end;

var
x: TBaseClass;
gn: IAddedStuff;
s: string;
begin
x := TMyNode.Create;
try
TMyNode(x).DefaultBehavior := TAddedStuffDefaultImplementation.Create;
Assert(Supports(x, IAddedStuff, gn));
WriteLn(gn.GetCaption);
finally
WriteLn('RefCount = ', x.RefCount);
// x.Free; // <-- FREE fails since FRefCount is 1
end;
ReadLn(s);
end.

最佳答案

如果您要委托(delegate) IAddedStuff,那么您还应该在另一个类上实现非默认行为,并通过构造函数注入(inject)传递它。

此外,如果您混合对象和接口(interface)引用,请确保引用计数不冲突。当使用接口(interface)委托(delegate)时,容器对象的引用会发生变化。

program Project1;

{$APPTYPE CONSOLE}

uses
Classes,
SysUtils;

type
IAddedStuff = interface(IInterface)
['{9D5B00D0-E317-41A7-8CC7-3934DF785A39}']
function GetCaption: string; {virtual;}
end;

TAddedStuffDefaultImplementation = class(TInterfacedObject, IAddedStuff)
function GetCaption: string; virtual;
end;

TAddedStuffOverriddenImplementation = class(TAddedStuffDefaultImplementation)
function GetCaption: string; override;
end;

TBaseClass = class(TInterfacedPersistent);

TMyNode = class(TBaseClass, IAddedStuff)
private
FAddedStuff: IAddedStuff;
property AddedStuff: IAddedStuff read FAddedStuff implements IAddedStuff;
public
constructor Create(const addedStuff: IAddedStuff);
end;

{ TAddedStuffDefaultImplementation }

function TAddedStuffDefaultImplementation.GetCaption: string;
begin
result := 'PROBLEM: CAPTION NOT OVERRIDDEN';
end;

{ TAddedStuffOverriddenImplementation }

function TAddedStuffOverriddenImplementation.GetCaption: string;
begin
Result := 'OK: Caption overridden';
end;

{ TMyNode }

constructor TMyNode.Create;
begin
FAddedStuff := addedStuff;
end;

var
x: TBaseClass;
gn: IAddedStuff;
begin
x := TMyNode.Create(TAddedStuffOverriddenImplementation.Create);
try
Assert(Supports(x, IAddedStuff, gn));
WriteLn(gn.GetCaption);
finally
x.Free;
end;
Readln;
ReportMemoryLeaksOnShutdown := True;
end.

编辑:

经过评论中的讨论,我提出以下建议:

program Project1;

{$APPTYPE CONSOLE}

uses
Classes,
SysUtils;

type
IAddedStuff = interface(IInterface)
['{9D5B00D0-E317-41A7-8CC7-3934DF785A39}']
function GetCaption: string;
end;

TAddedStuffDefaultImplementation = class(TInterfacedObject, IAddedStuff)
function GetCaption: string; virtual;
end;

TBaseClass = class(TInterfacedPersistent);

TMyNode = class(TBaseClass, IAddedStuff)
private
FAddedStuff: IAddedStuff;
property AddedStuff: IAddedStuff read FAddedStuff implements IAddedStuff;
public
constructor Create;
end;

TAddedStuffOverriddenImplementation = class(TAddedStuffDefaultImplementation)
private
FMyNode: TMyNode;
public
constructor Create(AMyNode: TMyNode);
function GetCaption: string; override;
end;

{ TAddedStuffDefaultImplementation }

function TAddedStuffDefaultImplementation.GetCaption: string;
begin
result := 'PROBLEM: CAPTION NOT OVERRIDDEN';
end;

{ TMyNode }

constructor TMyNode.Create;
begin
FAddedStuff := TAddedStuffOverriddenImplementation.Create(Self);
end;

{ TAddedStuffOverriddenImplementation }

constructor TAddedStuffOverriddenImplementation.Create(AMyNode: TMyNode);
begin
FMyNode := AMyNode;
end;

function TAddedStuffOverriddenImplementation.GetCaption: string;
begin
Result := 'OK: Caption overridden';
end;


var
x: TBaseClass;
gn: IAddedStuff;
begin
x := TMyNode.Create;
try
Assert(Supports(x, IAddedStuff, gn));
WriteLn(gn.GetCaption);
finally
x.Free;
end;
ReadLn;
ReportMemoryLeaksOnShutdown := True;
end.

关于delphi - 接口(interface)委托(delegate)+重写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24454572/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com