Duncan Lukkenaer
Duncan Lukkenaer

Reputation: 13914

Two objects need each other

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

Answers (3)

Fabjan
Fabjan

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

squill25
squill25

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

CodeCaster
CodeCaster

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

Related Questions