Reputation: 13914
Basically I have 3 classes: Game
, Level
and Player
(which is a GameObject
). Stripped to the bare minimum it looks something like this:
class Game
{
private Level[] levels;
private Player player;
public Game()
{
levels = new []{new Level(player)};
player = new Player(levels[0]);
}
}
class Level
{
private List<GameObject> gameObjects;
public Level(Player player)
{
gameObjects.Add(player);
}
public void DoSomething() {}
}
class Player : GameObject
{
private Level level;
public Player(Level level)
{
this.level = level;
level.DoSomething();
}
}
abstract class GameObject {}
Is it possible to make this work somehow? player
must be created inside Game
.
Upvotes: 1
Views: 1061
Reputation: 13676
Well, next time add Unity
tag to your question.
As it is now it is not going to work because currently Player
class requires instance of Level
class (in constructor) and Level
class requires instance of Player
class - this makes circular dependence and neither object can be instantiated. So first of all we should break it by removing Player
to Level
aggregation. Because of condition that we have (Player
must be instantiated only inside Game
class) we should mark it as abstract
:
abstract class AbstractPlayer : GameObject
{
public Level level { get; set; }
}
Now we can modify Game
class with new logic and add nested concrete Player
class that inherits from AbstractPlayer
:
class Game
{
private List<Level> levels;
private Player player;
public Game()
{
player = new Player();
Levels.Add(player);
}
// uncomment this method if you need it
//public Player CreatePlayer()
//{
// return new Player();
//}
private class Player : AbstractPlayer
{
public Player()
{
}
}
}
class Level
{
private List<GameObject> gameObjects;
public Level(Player player)
{
gameObjects.Add(player);
player.Level = this;
}
public void DoSomething() {}
}
Upvotes: 0
Reputation: 1208
As stated before, you can't instantiate one object without already having the other. If you want to keep the design you have now a solution would be to have a Game
reference in each other class, like this:
class Level
{
private Game game;
public Level(Game game)
{
this.game = game;
}
}
class Player
{
private Game game;
public Player(Game game)
{
this.game = game;
}
}
You would construct them inside the Game class like this:
levels = { new Level(this) } // (this refers to the instance of Game)
player = new Player(this);
since the constructors accept an instance of Game
Then to access the levels or player object, you would do this inside Level
or Player
:
this.game.levels
or
this.game.player
Upvotes: 1
Reputation: 151586
Fix your design. There is no "has-a" relation between player and level, in neither direction (or at least not in both). Or if you think there is, explain why tou think so.
As you found out, using your current design you can't instantiate the one without the other, creating a circular dependency. Of course, to "just make it work" you can create a property or setter method:
pubic class Player
{
private Level _level;
public Level Level
{
get { return _level; }
set { _level = value; }
}
// Or auto-implemented property
public Level Level { get; set; }
public Player()
{
}
}
(Or the same, but then for the Level).
Now you can instantiate a player without requiring a level:
var player = new Player();
var level = new Level(player);
player.Level = level;
Upvotes: 1