问题
这个问题在这里已有答案:
- 为什么要使用getter和setter / accessors? [已关闭] 38个答案
我目前正在开发一个简单的Java游戏,有几种不同的模式。我扩展了一个主要的Game类,将主要逻辑放在其他类中。尽管如此,主要的游戏类仍然相当沉重。
在快速浏览一下我的代码之后,其中大部分是Getters and Setters(60%),而其余部分则是游戏逻辑真正需要的。
一些谷歌搜索声称Getters和Setter是邪恶的,而其他人声称他们是良好的OO练习和优秀程序所必需的。
所以我该怎么做?应该是哪个?我应该为我的私人变量更改我的Getters和Setter,还是应该坚持使用它们?
#1 热门回答(338 赞)
还有一种观点认为,大多数情况下,使用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 / setter与公共领域的关系经常掩盖了更大的问题,因为对象以一种亲密的方式操纵彼此的内部状态,因此过于紧密耦合。
我们的想法是制定直接做你想做的事情的方法。一个例子是如何设置敌人的"活着"状态。你可能想要使用setAlive(boolean 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; }
#2 热门回答(175 赞)
- 非常邪恶:公共领域。
- 有点邪恶:吸气剂和制定者不需要他们。
- 好:只有在真正需要的地方才能获得getter和setter - 使类型暴露出"更大"的行为,恰好使用其状态,而不仅仅是将类型视为要由其他类型操纵的状态存储库。
这实际上取决于情况 - 有时你真的只想要一个愚蠢的数据对象。
#3 热门回答(42 赞)
你已经有了很多很好的答案,所以我只给我两分钱。吸气剂和制定者非常非常邪恶。它们基本上让你假装隐藏你的对象的内部,当你所做的大部分时间被抛在冗余的代码中,没有什么可以隐藏内部状态。对于一个简单的POJO,没有理由不能用obj.name ="Tom"替换getName()和setName()。
如果方法调用只是替换赋值,那么你通过优先选择方法调用获得的只是代码膨胀。不幸的是,该语言已经在JavaBeans规范中规定了getter和setter的使用,因此Java程序员被迫使用它们,即使这样做也毫无意义。
幸运的是,Eclipse(以及可能还有其他IDE)可以让你自动生成它们。对于一个有趣的项目,我曾经在XSLT中为它们构建了一个代码生成器。但是,如果有一件事我会在Java中摆脱它,它过度依赖于getter和setter。