Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
924 views
in Technique[技术] by (71.8m points)

oop - What's the deal with Java's public fields?

I've been reading two articles (1)(2) on javaworld.com about how all class fields should be private and getter/setter methods are just as bad. An object should act on the data it has rather than allowing access to it.

I'm currently working on a University assignment for Connect Four. 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.

At the start of design I was representing Points on the board as two element int arrays, however that got annoying when creating points or referencing components of them.

So, the class:

public class Point {
    public int x;
    public int y;
    public Point(int x, int y){
        this.x = x;
        this.y = y;
    }
}

Perfect in every way I can think of. Except it breaks every rule I've learned. Have I sinned?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...