Reputation: 391
I'm modeling a board, I wanted to make it as generic as I can,I also wanna avoid casting at all cost, because it's a bad practice!
Also, My code is completely working as right now, but I know as soon as I start working with Cell class and extend it, it'll be problematic!
Cell.java
public class Cell<T> {
private t value;
public Cell(T value) {
this.value = value;
}
// setters and getters
}
Board.java
import java.lang.reflect.Array;
public abstract class Board<T, E extends Cell<T>> {
protected E[][] cells;
protected Board(Class<? extends E> c) {
cells = (E[][])Array.newInstance(c, 6, 7);
}
protected void resetBoard(T resteVal) {
for (int i = 0; i < cells.length; i++)
for (int j = 0; j < cells[i].length; j++)
cells[i][j]= (E) new Cell<T>(); //HERE IS THE QUESTION
}
}
Game.java
public interface Game {
boolean islegalMove();
boolean isWin();
void move();
void resetGame();
void getScore();
}
Connect4.java
public class Connect4<E extends Cell<Integer>> extends Board<Integer,E> implements Game {
public Connect4(Class<? extends E> c) {
super(c);
}
// override methods
}
Upvotes: 0
Views: 69
Reputation: 33726
Replace this protected E[][] cells;
by protected Cell<T>[][] cells;
public abstract class Board<T, E extends Cell<T>> {
protected Cell<T>[][] cells;
@SuppressWarnings("unchecked")
public Board(Class<? extends E> c) {
cells = (E[][])Array.newInstance(c, 6, 7);
}
protected void resetBoard(T resteVal) {
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
Cell<T> cell = new Cell<T>();
cell.setValue(resteVal);
cells[i][j] = cell; //HERE IS MY REPLACEMENT
}
}
}
}
Upvotes: 1
Reputation: 18255
I think the problem is in architecture.
You have define Cell<T>
class (e.g. it could be extendable).
Then you define an abstract Board
, that could work with custom Cell
.
public abstract class Board<T, E extends Cell<T>> {
// why do not use T[][] cells instead?
protected final E[][] cells;
protected Board(E[][] cells) {
this.cells = cells;
}
// we hole Cell instances inside this class, so no need to create new ones
protected void resetBoard(T resetVal) {
for (int i = 0; i < cells.length; i++)
for (int j = 0; j < cells[i].length; j++)
cells[i][j].setValue(resetVal);
}
}
And finally, we could defeine an concrete board with concrete cell instance.
public final class MagicBoard<T> extends Board<T, MagicBoard.MagicCell<T>> {
public MagicBoard(Supplier<MagicCell<T>> supplier) {
//noinspection rawtypes,unchecked
super(new MagicCell[6][7]);
}
public static final class MagicCell<T> extends Cell<T> { }
}
Resume:
Abstract class Board
should not ware about concrete cell instance creating. Maximum, it could accept Supplier
from child class to delegate this work to concrete class 'MagicBoard' (only this class knows what type of Cell
should be created).
Try to avoid useless Cell
instance creating. If you hold it inside Board
and do not share it outside it, then reuse it. Just reset the value.
Question! I do not know whole code, but if your Cell
contains only one value, you could avoid using Cell
and use protected final T[][] cells;
instead (I think, that Board
should contains all logic for working with Cell
, but cells itself should not be very clever - just keep simple value). But this is only my opinion.
Upvotes: 1