Is it okay to instantiate an object inside a class [] – samuel tober
In java, there is no code outside a class. Therefore the question should be Is it okay to instantiate an object inside an object of a different class?
in order to access that object's methods? Say for example that I create a Scoreboard inside the GameBoard class only to be able to access Scoreboard's methods, would that be considered "good practice"? – samuel tober
You will find many programmers saying "Yes, of cause."
But my understanding is different.
Classes in general fall into 2 logical types: Data Transfer objects (DTOs) and others.
DTOs are special classes that have no (business) logic of their own, just getters. Usually they also have setters, but IMHO they soudn't unless required by a framework...
Classes of the other type provide business logic that works on data passed in via method Parameters (most likely in form of DTOs). Objects of such classes sometimes need to collaborate with other objects, so called dependencies. IMHO the instantiation of dependencies is NOT a responsibility of a class (Separation of concerns). Therefore any object should not instantiate the dependencies it works with itself.
Nevertheless it may instanciate dependensies for the objects it colaborates, but the better way is to use a dependency injection framework.
Is it okay to instantiate an object inside a class [] – samuel tober
In java, there is no code outside a class. Therefore the question should be Is it okay to instantiate an object inside an object of a different class?
in order to access that object's methods? Say for example that I create a Scoreboard inside the GameBoard class only to be able to access Scoreboard's methods, would that be considered "good practice"? – samuel tober
You will find many programmers saying "Yes, of cause."
But my understanding is different.
Classes in general fall into 2 logical types: Data Transfer objects (DTOs) and others.
DTOs are special classes that have no (business) logic of their own, just getters. Usually they also have setters, but IMHO they soudn't unless required by a framework...
Classes of the other type provide business logic that works on data passed in via method Parameters (most likely in form of DTOs). Objects of such classes sometimes need to collaborate with other objects, so called dependencies. IMHO the instantiation of dependencies is NOT a responsibility of a class (Separation of concerns). Therefore any object should not instantiate the dependencies it works with itself.
Nevertheless it may instanciate dependensies for the objects it colaborates, but the better way is to use a dependency injection framework.
[edit] I thing your code does not reflect this principles. – Timothy Truckle 14 hours ago
I think your code does not reflect this principles. – Timothy Truckle 14 hours ago
So I'd start by introducing a CellPosition
class holding x and y coordinates and a Direction
class that can create a new CellPosition
from a given one as needed.
Then I'd create lines by associating a CellPosition
(start point) with a Direction
in a Map<CellPosition,Direction>.
Finaly I'Finally I'd create a method than takes a CellPosition
and a Direction
and checks if all cells in than direction belong to the same player..
[edit] I thing your code does not reflect this principles. – Timothy Truckle 14 hours ago
So I'd start by introducing a CellPosition
class holding x and y coordinates and a Direction
class that can create a new CellPosition
from a given one as needed.
Then I'd create lines by associating a CellPosition
(start point) with a Direction
in a Map<CellPosition,Direction>.
Finaly I' create a method than takes a CellPosition
and a Direction
and checks if all cells in than direction belong to the same player..
I think your code does not reflect this principles. – Timothy Truckle 14 hours ago
So I'd start by introducing a CellPosition
class holding x and y coordinates and a Direction
class that can create a new CellPosition
from a given one as needed.
Then I'd create lines by associating a CellPosition
(start point) with a Direction
in a Map<CellPosition,Direction>.
Finally I'd create a method than takes a CellPosition
and a Direction
and checks if all cells in than direction belong to the same player..
class CellPosition {
private final int x, y;
CellPosition(int x, int y){
this.x = x;
this.y = y;
}
public int getX(){return x;}
public int getY(){return y;}
}
interface Direction {
CellPosition next(CellPosition current);
}
enum Player{NONE,P1,P2};
class GameEndChecker{
static class PlayerWon entends Exception {
// IMHO winning the game is an Exception with respect to the normal game flow
// since we have two "game end" conditions the calling code would become
// more complex when using a more complex return state to avoid the exception.
// this does not mean that an Exception is always appropriate to signal a winner...
private final Player winner;
PlayerWon(Player winner){ this.winner = winner;
@Override
public String getMessage(){
return "winner is: Player "+winner;
}
}
private final Player[][] board;
private final Map<CellPosition,Direction> lines;
GameEndChecker(Player[][] board){
this.board = board;
addHorizontalLines(lines);
addDiagonalLines(lines);
addVerticalLines(lines);
}
private addHorizontalLines(Map<CellPosition,Direction> lines){
for(int i =0, i< board.length, i++){
lines.put(new CellPosition(i,0), cellPosition-> new CellPosition(0,cellPosition.getY()+1));
}
}
private addDiagonalLines(Map<CellPosition,Direction> lines){
lines.put(new CellPosition(0,0), cellPosition-> new CellPosition(cellPosition.getX()+1,cellPosition.getY()+1));
lines.put(new CellPosition(2,0), cellPosition-> new CellPosition(cellPosition.getX()-1,cellPosition.getY()+1));
}
private addVerticalLines(Map<CellPosition,Direction> lines){
for(int i =0, i< board.length, i++){
lines.put(new CellPosition(0,i), cellPosition-> new CellPosition(cellPosition.getX()+1,0));
}
}
public boolean isGameEnd() throws PlayerWon{
boolean hasFreeFields=false;
for(Map.Entry<CellPosition,Direction>line : lines){
CellPosition currentCell = line.getKey();
// Sets hold unique values, doubles get filtered out.
Set<Player> lineOwners = new HashSet();
for(int i =0, i< board.length, i++){
Player fieldOwner= board[currentCell.getX()][currentCell.getY()]
currentCell = line.value().next(currentCell);
lineOwners.add(fieldOwner);
if(Player.NONE.equals(fieldOwner))
hasFreeFields==true;hasFreeFields=true;
}
if(1==lineOwners.size()&& !lineOwners.contains(Player.NONE))
// one player owns a complete line.
throw new PlayerWon(lineOwners.iterator().next());
}
return !hasFreeFields;
}
}
class CellPosition {
private final int x, y;
CellPosition(int x, int y){
this.x = x;
this.y = y;
}
public int getX(){return x;}
public int getY(){return y;}
}
interface Direction {
CellPosition next(CellPosition current);
}
enum Player{NONE,P1,P2};
class GameEndChecker{
static class PlayerWon entends Exception {
// IMHO winning the game is an Exception with respect to the normal game flow
// since we have two "game end" conditions the calling code would become
// more complex when using a more complex return state to avoid the exception.
// this does not mean that an Exception is always appropriate to signal a winner...
private final Player winner;
PlayerWon(Player winner){ this.winner = winner;
@Override
public String getMessage(){
return "winner is: Player "+winner;
}
}
private final Player[][] board;
private final Map<CellPosition,Direction> lines;
GameEndChecker(Player[][] board){
this.board = board;
addHorizontalLines(lines);
addDiagonalLines(lines);
addVerticalLines(lines);
}
private addHorizontalLines(Map<CellPosition,Direction> lines){
for(int i =0, i< board.length, i++){
lines.put(new CellPosition(i,0), cellPosition-> new CellPosition(0,cellPosition.getY()+1));
}
}
private addDiagonalLines(Map<CellPosition,Direction> lines){
lines.put(new CellPosition(0,0), cellPosition-> new CellPosition(cellPosition.getX()+1,cellPosition.getY()+1));
lines.put(new CellPosition(2,0), cellPosition-> new CellPosition(cellPosition.getX()-1,cellPosition.getY()+1));
}
private addVerticalLines(Map<CellPosition,Direction> lines){
for(int i =0, i< board.length, i++){
lines.put(new CellPosition(0,i), cellPosition-> new CellPosition(cellPosition.getX()+1,0));
}
}
public boolean isGameEnd() throws PlayerWon{
boolean hasFreeFields=false;
for(Map.Entry<CellPosition,Direction>line : lines){
CellPosition currentCell = line.getKey();
// Sets hold unique values, doubles get filtered out.
Set<Player> lineOwners = new HashSet();
for(int i =0, i< board.length, i++){
Player fieldOwner= board[currentCell.getX()][currentCell.getY()]
currentCell = line.value().next(currentCell);
lineOwners.add(fieldOwner);
if(Player.NONE.equals(fieldOwner))
hasFreeFields==true;
}
if(1==lineOwners.size()&& !lineOwners.contains(Player.NONE))
// one player owns a complete line.
throw new PlayerWon(lineOwners.iterator().next());
}
return !hasFreeFields;
}
}
class CellPosition {
private final int x, y;
CellPosition(int x, int y){
this.x = x;
this.y = y;
}
public int getX(){return x;}
public int getY(){return y;}
}
interface Direction {
CellPosition next(CellPosition current);
}
enum Player{NONE,P1,P2};
class GameEndChecker{
static class PlayerWon entends Exception {
// IMHO winning the game is an Exception with respect to the normal game flow
// since we have two "game end" conditions the calling code would become
// more complex when using a more complex return state to avoid the exception.
// this does not mean that an Exception is always appropriate to signal a winner...
private final Player winner;
PlayerWon(Player winner){ this.winner = winner;
@Override
public String getMessage(){
return "winner is: Player "+winner;
}
}
private final Player[][] board;
private final Map<CellPosition,Direction> lines;
GameEndChecker(Player[][] board){
this.board = board;
addHorizontalLines(lines);
addDiagonalLines(lines);
addVerticalLines(lines);
}
private addHorizontalLines(Map<CellPosition,Direction> lines){
for(int i =0, i< board.length, i++){
lines.put(new CellPosition(i,0), cellPosition-> new CellPosition(0,cellPosition.getY()+1));
}
}
private addDiagonalLines(Map<CellPosition,Direction> lines){
lines.put(new CellPosition(0,0), cellPosition-> new CellPosition(cellPosition.getX()+1,cellPosition.getY()+1));
lines.put(new CellPosition(2,0), cellPosition-> new CellPosition(cellPosition.getX()-1,cellPosition.getY()+1));
}
private addVerticalLines(Map<CellPosition,Direction> lines){
for(int i =0, i< board.length, i++){
lines.put(new CellPosition(0,i), cellPosition-> new CellPosition(cellPosition.getX()+1,0));
}
}
public boolean isGameEnd() throws PlayerWon{
boolean hasFreeFields=false;
for(Map.Entry<CellPosition,Direction>line : lines){
CellPosition currentCell = line.getKey();
// Sets hold unique values, doubles get filtered out.
Set<Player> lineOwners = new HashSet();
for(int i =0, i< board.length, i++){
Player fieldOwner= board[currentCell.getX()][currentCell.getY()]
currentCell = line.value().next(currentCell);
lineOwners.add(fieldOwner);
if(Player.NONE.equals(fieldOwner))
hasFreeFields=true;
}
if(1==lineOwners.size()&& !lineOwners.contains(Player.NONE))
// one player owns a complete line.
throw new PlayerWon(lineOwners.iterator().next());
}
return !hasFreeFields;
}
}
- 850
- 1
- 8
- 18