I have a Player class in a separate unit as follows:
TPlayer = class
private
...
FWorld: TWorld;
...
public
...
end;
I also have a World class in a separate unit as follows:
TWorld = class
private
...
FPlayer: TPlayer;
...
public
...
end;
I have done it this way so that the Player can get data from the world via FWorld, and so that the other objects in the world can get the player data in a similar manner.
As you can see this results in a circular reference (and therefore does not work). I have read that this implies bad code design, but I just can't think of any better other way. What could be a better way to do it?
Cheers!
Every once in a while this is called for, and then you do it like this:
//forward declaration:
TWorld = class;
TPlayer = class
private
FWorld: TWorld;
public
end;
TWorld = class
private
FPlayer: TPlayer;
public
end;
Just like Ozan said : most of the time, a good answer is to create a base class with virtual methods :
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;
...
or, with a similar effect, publish an interface :
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;
...
Depending on how your code works, you may want to hide the World behind an abstract layer (as in the above examples) or the Player (as suggested by Ozan).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With