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

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


当前回答

我只是想补充一点,即使有时它们对于变量/对象的封装和安全是必要的,如果我们想编写一个真正的面向对象的程序,那么我们需要停止过度使用附件,因为有时我们在不真正必要的情况下非常依赖它们,这几乎与我们将变量公开一样。

其他回答

我想发布一个我刚刚完成的真实世界示例:

背景-我使用休眠工具为我的数据库生成映射,这是一个我在开发时正在更改的数据库。我更改数据库模式,推送更改,然后运行hibernate工具来生成java代码。在我想向这些映射实体添加方法之前,一切都很好。如果我修改了生成的文件,则每次对数据库进行更改时都会覆盖这些文件。所以我这样扩展生成的类:

package com.foo.entities.custom
class User extends com.foo.entities.User{
     public Integer getSomething(){
         return super.getSomething();             
     }
     public void setSomething(Integer something){
         something+=1;
         super.setSomething(something); 
     }
}

我上面所做的是用我的新功能(something+1)覆盖超类上的现有方法,而不需要接触基类。如果你在一年前写了一个类,并且想在不改变基类的情况下升级到第2版(测试噩梦),也是同样的情况。希望这会有所帮助。

我只想抛出注释的概念:@getter和@settier。使用@getter,您应该能够obj=class.field,但不能使用class.field=obj。使用@settier,反之亦然。使用@getter和@setter,您应该能够同时做到这两个。这将通过在运行时不调用平凡的方法来保持封装并减少时间。

我花了很长时间来思考Java案例,我相信真正的原因是:

接口的代码,而不是实现接口只指定方法,不指定字段

换句话说,在接口中指定字段的唯一方法是提供一个用于写入新值的方法和一个用于读取当前值的方法。

这些方法是臭名昭著的getter和setter。。。。

DataStructure和Object之间存在差异。

数据结构应该暴露其内部而不是行为。

一个物体不应该暴露其内部,但它应该暴露其行为,这也被称为德米特定律

大多数DTO被认为是一种数据结构,而不是对象。他们应该只公开自己的数据,而不是行为。在数据结构中设置Setter/Getter将暴露行为,而不是其中的数据。这进一步增加了违反德梅特定律的可能性。

鲍勃叔叔在他的《干净的代码》一书中解释了得墨忒耳定律。

有一种著名的启发式方法叫做得墨忒耳定律,它说:模块不应该知道它的对象的内部结构操纵。正如我们在上一节中看到的,对象隐藏其数据并暴露操作。这意味着对象不应公开其通过访问器的内部结构,因为这样做是为了暴露,而不是隐藏其内部结构。更准确地说,德米特定律说C类的方法f应仅调用以下方法:Cf创建的对象作为参数传递给f的对象保存在C的实例变量中的对象该方法不应在任何允许的函数返回的对象上调用方法。换句话说,与朋友交谈,而不是与陌生人交谈。

因此,根据这一点,LoD违规的例子是:

final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();

在这里,函数应该调用它的直接朋友的方法,这里是ctxt,它不应该调用它直接朋友的朋友的方法。但该规则不适用于数据结构。所以在这里,如果ctxt、option、scratchDir是数据结构,那么为什么要用一些行为包装它们的内部数据,并违反LoD。

相反,我们可以这样做。

final String outputDir = ctxt.options.scratchDir.absolutePath;

这满足了我们的需求,甚至没有违反LoD。

灵感来源于Robert C.Martin(Bob叔叔)的“清洁代码”

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