简体   繁体   中英

Create a board made of Cells able host a Generic value

I'm working on a project( a game ) which will have a board to play on.

I want to make this board as generic as possible in order to be able to re-use the code for a possible other game.

public class Board {
    private int rows;
    private int cols;
    private Box[][] board;

    public Board(int rows, int cols){
        Box[][] board = new Box[rows][cols];
        for (int row = 0; row < this.rows; row++){
            for (int col = 0; col < this.cols; col++){
                board[row][col] = new Box();
            }
        }
    }

    public int getCols(){return this.cols;}
    public int getRows(){return this.rows;}

    public Piece getContentAtPos(int row, int col){
        return board[row][col].getContent();
    }
}

This is the Board class. The problem here is that I have to return a Piece object with the getContentAtPos() method because the Box ( Cell ) class is like this:

public class Box {
    private boolean empty;
    private Piece content;

    public Box(){
        empty = true;
    }

    public Box(Piece piece){
        empty = false;
        this.content = piece;
    }

    public boolean isEmpty(){
        return empty;
    }

    public Piece getContent(){
        if (!empty) {
            return content;
        } else {
            return null;
        }
    }
}

Whereas, the ideal for me would be the class Box to be able to host any type of object and return this generic object with getContentAtPos() via the Box getContent() method.

My generic Box class.

public class Box<T>{
    private boolean empty;
    private T content;

    public Box(){
        empty = true;
    }

    public Box(T content){
        this.content = content;
        empty = false;
    }

    public boolean isEmpty(){
        return empty;
    }

    public T getContent(){
        if (!isEmpty()){
            return content;
        }
        return null;
    }

    public T setContent(Object content){
        this.content = content;
    }
}

But what do I need to change in the Board class?

What return value shall I put there?

You should create interface that every class you will return in the future will implement. This way you will be sure that return type will implement interface and have defined behaviour.

    public interface ReturnableBox { 
          public boolean isEmpty();
    }
    public class Board {

       private int rows;
       private int cols;
       private ReturnableBox [][] board;
   }
   public class Box implements ReturnableBox {
   //...
   }

the ideal for me would be the class Box to be able to host any type of object and return this generic object with getContentAtPos via the Box getContent method

I guess you expect your game pieces to declare a certain behavior. If so, Box doesn't need to store an arbitrary object, but an object of type representing a contract that encompass all the methods which a game piece is expected to have.

In other words, you can define an interface, let's say Piece , which will have several implementations:

public interface Piece {
    // behavior of game pieces
}

public class MyGamePiece implements Piece {
    // implementations
}

You don't need to make Box class to be generic, instead it can contain a field of type Piece :

public class Box {
    private boolean empty;
    private Piece content;
    
    // constractor and methods

    public void setContent(Object content){
        this.content = content;
    }

    public Piece getContent(){
        return content;
    }
}

That gives you a freedom to provide any implementation of the Peice via constructor of the Box class or true the setter. It means you can design the core part of the gave having only one implementation MyGamePiece , and later on add a few more classes like NewGamePeace (names should reflect the purpose of the class if the clear and concise way, it's just dummy example).

The key point is that you can benefit from the polymorphism and don't have to change the previously designed and tested code in order to make it work with new classes (that called a late binding ):

Box box = new Box();
box.setContent(new MyGamePiece());
box.setContent(new NewGamePeace()); // in order to make this line compile only need to introde the `NewGamePeace` class itself

And method getContentAtPos() will also return an object of type Piece .

I want to make this board as generic as possible in order to be able to re-use the code for a possible other game.

That's a laudable aim.

Your classes have to be loosely coupled and narrow focused in order to be reusable. Ie each class should a narrow and well-defined set of functionality and be aware only of those object that are crucial for it work (reduce coupling).

And you can make the necessary coupling loose ( high coupling isn't good, but classes can't interact without coupling at all, you need to maintain balance ) by introducing interfaces as shown above.

Even if eventually you would not use this code in other project, keeping it loosely coupled is beneficial because it makes it easier to maintain and expand the code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM