循环参考修复?

时间:2010-04-29 15:16:29

标签: delphi pascal

我在一个单独的单元中有一个Player类,如下所示:

TPlayer = class
private
  ...
  FWorld: TWorld;
  ...
public
  ...
end;

我在一个单独的单位中也有一个世界级如下:

TWorld = class
private
  ...
  FPlayer: TPlayer;
  ...
public
  ...
end;

我这样做是为了让玩家可以通过FWorld从世界获取数据,这样世界上的其他对象就可以以类似的方式获取玩家数据。

正如您所看到的,这会产生循环引用(因此不起作用)。我已经读到这意味着糟糕的代码设计,但我想不出更好的其他方式。什么是更好的方法呢?

干杯!

3 个答案:

答案 0 :(得分:6)

每隔一段时间就会召唤一次,然后你这样做:

//forward declaration:
TWorld = class;

TPlayer = class
private 
  FWorld: TWorld;
public
end;

TWorld = class
private
  FPlayer: TPlayer;
public
end;

答案 1 :(得分:4)

就像Ozan所说的那样:大多数时候,一个很好的答案就是用虚方法创建一个基类:

unit BaseWorld;
TBaseWorld = class
  function GetWorldInfo() : TWorldInfo; virtual; {abstract;}
...

unit Player;
TPlayer = class
  FWorld : TBaseWorld;
  constructor Create( AWorld : TBaseWorld );
...

unit RealWorld;
TWorld = class(TBaseWorld)
  function GetWorldInfo() : TWorldInfo; override;
  ...

TWorld.AddPlayer();
begin
  TPlayer.Create(Self);
end;
...

或者,具有类似的效果,发布一个界面:

unit WorldIntf;
IWorldInterface = interface
  function GetWorldInfo() : TWorldInfo;
...

unit Player;
TPlayer = class
  FWorld : IWorldInterface;
  constructor Create( AWorld : IWorldInterface );
...

unit RealWorld;
TWorld = class(TInterfacedObject, IWorldInterface)
  function GetWorldInfo() : TWorldInfo;
  ...

TWorld.AddPlayer();
begin
  TPlayer.Create(Self);
end;
...

根据代码的工作方式,您可能希望隐藏抽象层(如上例所示)或播放器(如Ozan所建议)背后的世界。

答案 2 :(得分:0)

将两个类放在一个单元中,或者提取其中一个类的抽象基类,而不引用另一个类。然后在其他类定义中引用此抽象基类:

uses UAbstractPlayer;
TWorld = class
...
private
  FPlayer: TAbstractPlayer;
...

如果在TWorld中创建TPlayer,则可以在implementation use子句中引用原始TPlayer单元。否则,您根本不需要引用原始的TPlayer单元。

这称为dependency inversion