4

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

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

我在一个单独的单元中也有一个世界级,如下所示:

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

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

如您所见,这会导致循环引用(因此不起作用)。我读过这意味着糟糕的代码设计,但我想不出更好的其他方式。有什么更好的方法来做到这一点?

干杯!

4

3 回答 3

6

每隔一段时间就会要求这样做,然后你会这样做:

//forward declaration:
TWorld = class;

TPlayer = class
private 
  FWorld: TWorld;
public
end;

TWorld = class
private
  FPlayer: TPlayer;
public
end;
于 2010-04-30T00:47:13.947 回答
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 建议)后面。

于 2010-04-30T07:12:03.240 回答
0

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

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

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

这称为依赖倒置

于 2010-04-30T02:28:07.047 回答