'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 |
|---|
