gilc
gilc

Reputation: 61

Accessing methods in higher class in Java

Context

I'm making a 2D game in Java.

I have this Java scheme :

| Map | ---- | BlockGrid | ---- | Block |

where Map, BlockGrid and Block are Java classes.

Here, the Map class has a BlockGrid attribute and the BlockGrid class has a Block[ ][ ] attribute storing all the blocks in the grid.

My goal

I want to be able to access methods in my Map instance from my Block class. For example, I want to call spawnEntity(..) on the Map instance to spawn an Arrow or something.

Solutions ?

I thought about making spawnEntity(..) static but I know it is not a good practice since in order to spawn an entity, the Map need to be instanciated.

I also thought about passing my Map instance as parameter in each constructor. That way, BlockGrid and Block would have access to the instance and would be able to call methods.

My question

What is the best practice for this case ? Thank you.

Upvotes: 3

Views: 175

Answers (2)

Alex R
Alex R

Reputation: 3311

Generally, a good practice is to have loose coupling of unrelated components. This means that if you choose to make the methods of your Map class available to the Block class by passing down references you should consider doing that via an interface (see Omars answer). This way you can initialize your Blocks with objects of other classes instead of just Map instances if you later choose to do so.

But the second thing you should ask yourself if it really is a Blocks responsibility to be able to spawn entities? I would say no because a Block is probably just a representation of a location plus some structure (although I don't know the semantics of your program). By choosing a different way to structure your programm you avoid introducing circular dependencies (Map depends on Block, Block depends on Map) which are usually considered a really bad thing (among other things, because you get a high coupling of your components) and follow the Single responsibility principle (because Blocks are not responsible any longer for spawning entities).

In my opinion, you shouldn't allow accessing Maps from Blocks but instead make it Map responsibility to spawn entities. One way of doing it would be:

public final class Map {
    private final BlockGrid blockGrid;

    public Map(BlockGrid grid) {this.blockGrid = grid;}

    public void spawnEntityAt(int x, int y) {
        Block block = this.blockGrid.getBlockAt(x, y);
        // spawn the entity using information from 'block'

    }
}

final class BlockGrid {
    private final Block[][] grid;

    public BlockGrid(Block[][] grid) { this.grid = grid; }

    public Block getBlockAt(int x, int y) {
        return this.grid[x][y];
    }
}

final class Block {}

Upvotes: 1

Omar Silva
Omar Silva

Reputation: 301

Make an interface:

interface EntitySpawner {
    void spawnEntity(...);
}

Make your Map class implement this interface, then make BlockGrid accept EntitySpawner as an argument.

class Map implements EntitySpawner {

    private final BlockGrid grid = new BlockGrid(this);

    @Override
    public void spawnEntity(..) {
        // do something here
    }
}

Upvotes: 0

Related Questions