'How to initialize array of objects which have implemented a specific class

I have a class called 'Grid', which is supposed to be a 2D array of another class 'Cell'. However, the 'Cell' class is abstract and is supposed to be extended by the user of this library. How would I initialize this 2D array of 'Cells' inside the Grid class?

It is ensured that all the implementation of 'Cell' will only have a default constructor. I would like a way for the grid class to be initialized in an easy manner. For example, if 'MyCell' is a class that extends 'Cell', then I would like to have something like this: -

Grid grid = new Grid(10, 10, MyCell.class); //or something else

then the 2D array in the 'grid' instance should all be initialized with 'MyCell' default constructor. How do I go about doing this?

Currently, this is the following structure: -

public class Grid {
    int rows;
    int cols;
    Cell[][] cells;

    public Grid(int rows, int cols) {
        this.rows = rows;
        this.cols = cols;
        this.cells = new Cell[rows][cols];
        // How to initialize 'cells' array?
    }
}
public abstract class Cell {
    private Color color;

    protected Cell(Color color) {
        this.color = color;
    }

    public Color getColor() {
        return color;
    }
}

What I have thought/tried: -

  • Application of Factory pattern would have been well suited here, but the only problem is that the subclasses of 'Cell' don't exist yet...
  • I have tried solving this by accepting a 'Cell creator' lambda in the constructor: -
public interface CellCreator {
    public Cell create();
}

then inside the constructor,

public Grid(int rows, int cols, CellCreator cellCreator) {
    this.rows = rows;
    this.cols = cols;
    this.cells = new Cell[rows][cols];
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            cells[i][j] = cellCreator.create();
        }
    }
}

It seems to be the best solution right now.

  • Making Grid a generic class is not something that I would like, because I want Grid to be a 2D array of 'Cell' only and not any other class. Also, template arrays cannot be instantiated somehow.

  • Taking classname as parameter and instantiating using that doesn't work either because you cannot pass subclasses as arguments.

  • Reflection does not seem like a good solution (messy code, a lot of error handling): -

public Grid(int rows, int cols, String clazz) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
    this.rows = rows;
    this.cols = cols;
    this.cells = new Cell[rows][cols];
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            cells[i][j] = Class.forName(clazz).asSubclass(Cell.class).getDeclaredConstructor().newInstance();
        }
    }
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source