0

I'm practicing Java by making a program that can play some online puzzle games such as minesweeper, chess, etc. Since the games are all played on an orthogonal grid, I found the methods common to each game and tossed them in a class that has a 2-d array of elements I named Orthogonals. My first intuition was to let the squares of the board be generically typed:

public abstract class GridBoard <E extends Orthogonal>{
    private final E[][] board;
    public final int width;
    public final int height;

    public GridBoard(int width, int height){
        this.width=width;
        this.height=height;
        board= new E[][]();
    }

    /*...*/
}

Unfortunately, new E[][]() isn't possible for some important reasons. I would be happy using a constructor like public GridBoard(E[][] board), but I want Orthogonal to have methods like orthogonal.getNeighbor(NORTH), which require them to know which (final) board they're a part of. From what I can tell, there are a few different ways of getting around this limitation, but none of them feel like they simplify the design. My goal is to let MinesweeperBoards work with a MineSquare[][], but ChessBoards have ChessSquare[][], for example.

https://stackoverflow.com/a/18111163/8611351 shows how an array can be created, but the class of a generic can't be obtained dynamically. A class would have to be passed into the constructor, which adds needless complexity for the implementer.

Some answers to questions about similar patterns suggest letting the subclass of GameBoard fill the array with their own type of squares, and then casting each time the board is read from. Is this an acceptable practice? When are casting and instanceof considered acceptable design?

board doesn't need to be defined in the abstract class, and all of the methods in Orthogonal can rely on the concrete implementations. But that sounds like a great way to put repetitive code into every different game.

I could remove the Orthogonal class entirely and put the logic for navigating the board into GridBoard. But if I do that, there won't be as clean a way to write something like return square.neighbors().filter(MineSquare::isBomb).count().

I could change the class definition to GridBoard <E> and make Orthogonals a class that get created as needed and read Es from the board. This seems like the most reasonable solution, but I'm very curious about the best way to solve the array of subclasses problem if that wasn't an option. Is there a perk or drawback that I've overlooked?

Alex Sage
  • 25
  • 1
  • 4
  • 2
    *When are casting and `instanceof` considered acceptable design?* Rarely. Is there a reason you can't use a `List>` instead of an array? – shmosel Nov 19 '17 at 04:27
  • As for why it is a bad idea to mix arrays and generics, see: https://stackoverflow.com/a/18581313/1057429 – Nir Alfasi Nov 19 '17 at 04:32

0 Answers0