我在一个单独的单元中有一个Player类,如下所示:
TPlayer = class
private
...
FWorld: TWorld;
...
public
...
end;
我在一个单独的单位中也有一个世界级如下:
TWorld = class
private
...
FPlayer: TPlayer;
...
public
...
end;
我这样做是为了让玩家可以通过FWorld从世界获取数据,这样世界上的其他对象就可以以类似的方式获取玩家数据。
正如您所看到的,这会产生循环引用(因此不起作用)。我已经读到这意味着糟糕的代码设计,但我想不出更好的其他方式。什么是更好的方法呢?
干杯!
答案 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单元。