2

I dont think its pretty to use this as a class parameter because there could occur errors if the order of initialization of the objects is not right.

Whats best practise to avoid this?

Example:

public class Game{

    private Player p1, p2, currentPlayer;
    private Board board;

    Game() {
        board = new Board(this);
    }

    private boolean hasFieldsToBeClicked() {
            return board.checkFieldsToBeClicked();
        }
  • 4
    It's very common to pass `this` as a parameter to another constructor. I would not assume that it is a problem. – khelwood May 22 '18 at 07:58
  • Welcome to Stack Overflow. It's hard to give any concrete recommendations when we don't know the details of what you're trying to achieve. Why does the `Board` need to know about the `Game`, for example? If you can avoid the cyclic dependency, you're more likely to be able to avoid passing `this`. – Jon Skeet May 22 '18 at 07:58
  • 4
    @khelwood this *is* a problem, it's unsafe publication (i.e. you are leaking the reference to the `Game` before it has finished being initialized). – Andy Turner May 22 '18 at 07:58
  • @AndyTurner I see what you mean. I guess it depends on what you're doing with `this` when you get it. I assumed it was just so that `Board` could store a reference to the `Game` object for later. – khelwood May 22 '18 at 08:00
  • @DaisyShipton The Game class contains basically all the logic of the game. The `Board` class is basically the GUI. `Gam`e needs to be able to call methods from `Borad`. Maybe there is fundeamentally something wrong with that? – Fabian Zbinden May 22 '18 at 08:01
  • That doesn't explain why `Board` needs a reference to `Game` - it explains the reverse. (I'm not sure what you mean by the `Board` class being "the guy".) But basically it's worth considering whether you can refactor to avoid that dependency. If the board is just the data of what pieces are where, etc, why would it need to call into `Game`? – Jon Skeet May 22 '18 at 08:04
  • If you absolutely need the reference during construction, then you could consider making Board an inner class of Game. Then it gets a reference by default. Or you could consider adding a setter method, and set the Board/Game relationship after the constructor is complete. – matt May 22 '18 at 08:07
  • @DaisyShipton For example the `Game` class contains the current player. If the `Board` needs to display this, it has to be able to call ` dame.getCurrentPlayer()` – Fabian Zbinden May 22 '18 at 08:08
  • @matt If `Board` is an inner class of `Game`, that inherently has all the same possible pitfalls of passing `this` to `Board`'s constructor. – khelwood May 22 '18 at 08:08
  • @khelwood It isn't quit the same semantically because it is in the same class. – matt May 22 '18 at 08:13
  • @FabianZbinden: Perhaps it would be better for `Board.display()` to accept a `Game` parameter then? Or make the `Game` responsible for displaying the players? But it's *really* hard to discuss this with only bits and pieces of information. My advice is to try to redesign to avoid the cyclic dependency - but that's about all I can say without more concrete information. – Jon Skeet May 22 '18 at 08:14
  • @DaisyShipton I just need to know the possible options, I have not heard of before. So I note to myself: 1. Passing object as METHOD parameter instead of class parameter. 2. Create a setRelationship() Method outside of the constructor to avoid beeing it in the class constructor. Is this about the right way to go? – Fabian Zbinden May 22 '18 at 08:21
  • @FabianZbinden: Again, we can't know the "right" way to go without knowing more context. If you try to make your classes immutable, you can't have a `setRelationship` method, for example. (And even if they're mutable, you'd end up with a partially-initialized object until you called `setRelationship`. Is that a problem? It might be, or it might not be.) – Jon Skeet May 22 '18 at 08:24

2 Answers2

6

From a design point of view: just don't do it here!

Meaning: a Board represents a board. Does your chess board know about the game you are currently having, or not?

In other words: passing this can be ok, but as you pointed out, it can also be a problem. Thus the best practice is: only pass this if you have good reasons to. Especially when it occurs within the constructor and this is still in the process of being initialized.

Enabling a chess board to know about an ongoing game isn't really a good reason.

Keep in mind: your classes/objects should model the real world. Only establish relations that are meaningful!

So the real answer here would be to look into why your Board class needs to know about the Game class, to then get rid of that dependency.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • So let's say I want to get rid of the dependency. How do I realize `Board` being the GUI of something that happens in another class. I see no reason to keep track of a players score in the GUI class which in my case is `Board`, On the other hand I dont see much sense in initializing a label and filing it with the score as ouptut in the `Game` class. How do I get to know about the score if I should get rid of the dependency? (All this is just an example and a bit more complex) – Fabian Zbinden May 22 '18 at 08:18
  • 1
    @FabianZbinden: Perhaps `Board` shouldn't be the GUI then. Perhaps it should just be the data model for the board itself. Then create a separate GUI class which knows about both the `Game` and the `Board`, but which neither of *those* need to know about. Separation of concerns can solve a lot of these problems. – Jon Skeet May 22 '18 at 08:25
  • 1
    @FabianZbinden Exactly as Daisy is saying: merging the "business" logic of your board with any kind of UI representation is already a step in the wrong direction. – GhostCat May 22 '18 at 09:25
0

1) What about a builder, which creates the game and the board at first without the other. Then the builder can set the Board in the Game and the Game in the Board.

2) It seems the Board is an inherent part of the Game.

  • a) So you could use interfaces for Game and Board and implement both in one class.
  • b) If you want to separate the Game from the Board you could use an inner class for the Board within the Game.
LuCio
  • 5,055
  • 2
  • 18
  • 34