使用getter和setter(只获取和设置)而不是简单地为这些变量使用公共字段有什么好处?

如果getter和setter所做的不仅仅是简单的get/set,我可以很快地解决这个问题,但我不是100%清楚如何做到:

public String foo;

比:

private String foo;
public void setFoo(String foo) { this.foo = foo; }
public String getFoo() { return foo; }

而前者需要的样板代码要少得多。


当前回答

在纯面向对象的世界中,getters和setters是一种可怕的反模式。阅读本文:Getters/Setters。恶毒的时期简而言之,它们鼓励程序员将对象视为数据结构,这种类型的思考是纯过程的(如COBOL或C)。在面向对象的语言中,没有数据结构,只有暴露行为的对象(不是属性/财产!)

您可以在ElegantObjects(我的面向对象编程书)的第3.5节中找到更多关于它们的信息。

其他回答

很多人都在谈论二传手和二传手的优点,但我想扮演魔鬼代言人的角色。现在我正在调试一个非常大的程序,程序员们决定让所有的东西都变得更好和更好。这看起来不错,但这是一场逆向工程噩梦。

假设你正在查看数百行代码,你会发现:

person.name = "Joe";

这是一段非常简单的代码,直到你意识到它是一个setter。现在,您遵循该setter,发现它还设置了person.firstName、person.lastName、person.isHuman、person.hasReallyCommonFirstName,并调用person.update(),后者将查询发送到数据库等。哦,这就是发生内存泄漏的地方。

乍一看就理解一段本地代码是具有良好可读性的一个重要特性,getter和setter往往会打破这一特性。这就是为什么我尽量避免使用它们,并在使用它们时尽量减少它们所做的事情。

在面向对象的语言中,方法及其访问修饰符声明该对象的接口。在构造函数、访问器和赋值器方法之间,开发人员可以控制对对象内部状态的访问。如果变量被简单地声明为公共的,那么就没有办法规范这种访问。当我们使用setter时,我们可以限制用户所需的输入。这意味着这个变量的输入将通过一个适当的通道,通道是我们预先定义的。所以使用setter更安全。

因为从现在起2周(月、年),当您意识到setter需要做的不仅仅是设置值时,您还将意识到该属性已直接用于238个其他类:-)

从面向对象设计的角度来看,这两种选择都会削弱类的封装,从而对代码的维护造成损害。对于讨论,您可以查看这篇优秀的文章:http://typicalprogrammer.com/?p=23

谢谢,这真的澄清了我的想法。现在有10个(几乎)不使用getter和setter的好理由:

当您意识到您需要做的不仅仅是设置和获取值时,您可以将字段设为私有,这会立即告诉您直接访问它的位置。在那里执行的任何验证都只能是上下文无关的,而实际上很少进行这种验证。您可以更改设置的值-当调用者传递给您一个他们(震惊恐惧)希望您按原样存储的值时,这绝对是一场噩梦。你可以隐藏内部表示-太棒了,所以你要确保所有这些操作都是对称的,对吗?你已经将你的公共界面与表单下的更改隔离开来——如果你在设计一个界面,但不确定直接访问某个东西是否可行,那么你应该继续设计。一些库期望这样做,但并不多——反射、序列化、模拟对象都能很好地处理公共字段。通过继承这个类,您可以覆盖默认功能——换句话说,您不仅可以隐藏实现,而且可以使其不一致,从而真正混淆调用者。

最后三个我要离开(N/A或D/C)。。。