Public fields expose the representation of an object to its callers, i.e. if the representation has to change, so do the callers.
By encapsulating the representation, you can enforce how callers interact with it, and can change that representation without having to modify the callers provided the public api is unchanged. In any non-trivial program, encapsulation is necessary to achieve reasonable maintainability. However, while you need capsules, their proper granularity may be larger than a single class. For instance, it makes little sense to encapsulate an Iterator
from the internal representation of the Collection
it operates on.
With that out of the way, let's look at your example:
public class Point {
public int x;
public int y;
public Point(int x, int y){
this.x = x;
this.y = y;
}
}
The internal representation of that class is exceedingly unlikely to change, so hiding the structure of the representation by making the fields private has no benefit. However, I'd prevent callers from modifying a Point
once it has been constructed:
public class Point {
public final int x;
public final int y;
public Point(int x, int y){
this.x = x;
this.y = y;
}
}
so that a class that actually wishes to encapsulate its state can return its Point
without leaking its internal representation, and use a given Point in its representation without capturing it. This also fits nicely with the mathematical notion of a point, which has no identity or changing state.
In designing the program the Agents playing the Game need access to the Board's state (so they can decide what to move). They also need to pass this move to the Game so it can validate it as a legal move. And during deciding what to move pieces are grouped into Threats with a start and end Points.
Board, Threat and Point objects don't really do anything. They are just there to store related data that can be accessed in a human readable way.
Now this sounds like a wasted opportunity for encapsulation: The agents should really not be permitted to arbitrarily modify the board, but be restricted to legal moves. Why is it the responsibility of class Game
to decide what a legal move is, when the state being updated resides in class Board
? If the Board
were to validate the moves itself, no caller, and in particular no agent, could violate the rules of the game:
public class Board {
// private fields with state
// public methods to query state
public void perform(Move move) throws IllegalMoveException;
}