还有一种观点认为,大多数时候,使用 setter 仍然会通过允许您设置无意义的值来破坏封装。举一个非常明显的例子,如果你在游戏上有一个分数计数器,它只会上升,而不是
// Game
private int score;
public void setScore(int score) { this.score = score; }
public int getScore() { return score; }
// Usage
game.setScore(game.getScore() + ENEMY_DESTROYED_SCORE);
它应该是
// Game
private int score;
public int getScore() { return score; }
public void addScore(int delta) { score += delta; }
// Usage
game.addScore(ENEMY_DESTROYED_SCORE);
这也许是一个简单的例子。我想说的是,讨论 getter/setters 与公共领域往往会掩盖更大的问题,因为对象以亲密的方式操纵彼此的内部状态,因此过于紧密地耦合在一起。
这个想法是制造直接做你想做的事情的方法。一个例子是如何设置敌人的“活着”状态。你可能会想有一个 setAlive(布尔 alive)方法。相反,您应该拥有:
private boolean alive = true;
public boolean isAlive() { return alive; }
public void kill() { alive = false; }
这样做的原因是,如果您更改实现,使事物不再具有“活动”布尔值,而是具有“命中点”值,则可以在不破坏之前编写的两个方法的契约的情况下进行更改:
private int hp; // Set in constructor.
public boolean isAlive() { return hp > 0; } // Same method signature.
public void kill() { hp = 0; } // Same method signature.
public void damage(int damage) { hp -= damage; }