Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 接口委托+;最重要的_Delphi_Oop_Interface_Delegation - Fatal编程技术网

Delphi 接口委托+;最重要的

Delphi 接口委托+;最重要的,delphi,oop,interface,delegation,Delphi,Oop,Interface,Delegation,由于Delphi中缺少多重继承,我需要使用接口委托。这对我来说是一个非常新的主题,我在将重写与接口委托相结合时遇到了一个问题 类TMyNode必须继承自TBaseClass,并且需要实现IAddedStuff。我希望在TAddedStuffDefaultImplementation中有IAddedStuff的所有函数的默认实现,因此我不需要到处都有重复的getter/setter代码。因此,我使用DefaultBehavior委派了这些事情 问题是,TAddedStuffDefaultImple

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

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

问题是,
TAddedStuffDefaultImplementation
意味着要有虚拟方法,所以我想在
TMyNode
中直接重写它们。如果我编写
FDefaultImplementation:TAddedStuffDefaultImplementation而不是
fdefultimation:IAddedStuff

但是现在,由于某些原因,
TAddedStuffDefaultImplementation
将增加
x:TBaseClass的Ref计数器,因此无法将其释放。我该怎么办

我的简化复制代码如下:

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.
程序项目2;
{$APPTYPE控制台}
{$R*.res}
使用
System.SysUtils;
类型
IADDestuff=接口(IInterface)
[{9D5B00D0-E317-41A7-8CC7-3934DF785A39}]
函数GetCaption:string;{virtual;}
结束;
TAddedStuffDefaultImplementation=class(TInterfacedObject,IAddedStuff)
函数GetCaption:string;事实上的
结束;
TBASECASE=类别(TInterfacedObject);
TMyNode=class(TBaseClass,IAddedStuff)
私有的
FDefaultImplementation:TAddedStuffDefaultImplementation;
公众的
属性DefaultBehavior:TAddedStuffDefaultImplementation读取FDefaultImplementation
编写fdefultimationimplementation;
毁灭者毁灭;推翻
//--我的东西
//下面是我想在TMyNode中“覆盖”的一些函数。
//此处未声明的所有函数都应取自fdefaultimation。
函数GetCaption:string;{覆盖;}
结束;
{TAddedStuffDefaultImplementation}
函数TAddedStuffDefaultImplementation.GetCaption:string;
开始
结果:='问题:标题未被覆盖';
结束;
{TMyNode}
析构函数TMyNode.Destroy;
开始
如果已分配(FDEFultimation),则
开始
免费;
fdefultimation:=nil;
结束;
继承;
结束;
函数TMyNode.GetCaption:string;
开始
结果:='确定:标题被覆盖';
结束;
变量
x:TBaseClass;
gn:IAddedStuff;
s:字符串;
开始
x:=TMyNode.Create;
尝试
TMyNode(x).DefaultBehavior:=TAddedStuffDefaultImplementation.Create;
Assert(支持(x,IAddedStuff,gn));
WriteLn(gn.GetCaption);
最后
WriteLn('RefCount=',x.RefCount);

//十、免费;// 如果您正在委派
IAddedStuff
,那么您还应该在另一个类上实现非默认行为,并通过构造函数注入传递它

此外,如果混合对象引用和接口引用,请确保引用计数不冲突。使用接口委托时,容器对象的引用会发生更改

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.

我不熟悉界面,但我有一个问题
TMyNode
继承了
TBaseClass
IAddedStuff
TBaseClass
继承了
TInterfacedObject
TAddedStuffDef….
也继承了
TInterfacedObject
IadedStuff
所以基本上,如果TMyNode继承了
TAddedStuffDef….
的话,它不应该具有相同的函数集吗?对我来说似乎是双重的,但可能我错了:)TMyNode需要从TAddedStuffDefaultImplementation和TBaseClass继承。因为多重继承是不可能的,所以我需要做上面所有的事情:-(在我的简化示例中,TBaseClass没有额外的内容,因为它与问题无关。文档使用接口,而代码使用类引用-混合这是引用计数头痛的常见原因。TInterfacedObject的Anchestor是引用计数的(除非您更改此项)并且永远不应该被释放。好的,让我澄清一下。TInterfacedObject的AcheStor使用引用计数实现接口,这些对象实例的生存期由这些接口的引用计数控制。您永远不应该在这些对象上使用Free。这与TInterfacedPersistent不同,后者不实现引用c装载。非常感谢您的快速回复。我确实混合了对象和接口引用,因为这是进行“覆盖”的唯一可能性工作。由于某些原因,如果专用字段是对象引用,则会调用重写的变量,但当它是接口引用时则不会调用。您的代码解决了引用计数的问题,但遗憾的是,
TaddedStuffOverridedImplementation
无法访问
TMyNode
。其背后的思想是
TAddedStuffDefaultImplementation.GetCaption
只输出“未知”(某个常量),而
TMyNode.GetCaption
输出特定于数据的内容,如“User:Thomas”。在
TMyNode
中是否还必须有
GetCaption
,但仍然覆盖接口的默认实现(主要是getter和setter以及“未知”标题+图标)?您是否创建了
TaddedStuff DefaultImplementation
以在不同的其他类中重用它,而无需每次都实现
IAddedStuff
?否则,您可以将默认实现方法放在
TBaseClasseWithAddedStuff
中,使其虚拟化,然后在
TMyNode中重写它们de>。是的,
TAddedStuffDefaultImplementation
的目的是与al共享它