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

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


当前回答

在不支持“财产”(C++、Java)或在将字段更改为财产(C#)时需要重新编译客户端的语言中,使用get/set方法更容易修改。例如,向setFoo方法添加验证逻辑不需要更改类的公共接口。

在支持“真实”财产的语言中(Python、Ruby或Smalltalk?),没有必要使用get/set方法。

其他回答

事实上,考虑使用访问器而不是直接公开类的字段有很多很好的理由——不仅仅是封装和使未来的更改更容易。

以下是我知道的一些原因:

与获取或设置属性相关的行为的封装-这允许以后更容易地添加附加功能(如验证)。隐藏属性的内部表示形式,同时使用替代表示形式公开属性。隔离您的公共接口不受更改的影响——允许公共接口在实现更改时保持不变,而不影响现有用户。控制属性的生存期和内存管理(处置)语义——在非托管内存环境(如C++或Objective-C)中尤为重要。在运行时为属性更改时提供调试拦截点-在某些语言中,如果没有此功能,则很难调试属性更改为特定值的时间和位置。改进了与旨在针对属性getter/setter进行操作的库的互操作性——Mocking、Serialization和WPF应运而生。允许继承者通过重写getter/setter方法来更改属性的行为和公开方式的语义。允许getter/setter作为lambda表达式而不是值传递。获取器和设置器可以允许不同的访问级别-例如,获取可以是公共的,但集合可以受到保护。

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

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

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

我能想到一个原因,为什么你不希望一切都公开。

例如,您从未打算在类外部使用的变量可以被访问,甚至可以通过链变量访问(即object.item.origin.x)直接访问。

通过将所有内容都设为私有,并且仅将您想要扩展的内容以及可能在子类中引用的内容设为受保护的,并且通常只将静态最终对象设为公共,那么您就可以通过使用setter和getter访问您想要的程序内容来控制其他程序员和程序可以在API中使用什么,以及它可以访问什么,以及不能访问什么,或者可能是其他恰好使用您的代码的程序员,可以在您的程序中进行修改。

我们使用getter和setter:

可重用性在编程的后期执行验证

Getter和setter方法是访问私有类成员的公共接口。


封装咒语

封装的口头禅是将字段私有化,将方法公开化。

Getter方法:我们可以访问私有变量。Setter方法:我们可以修改私有字段。

尽管getter和setter方法没有添加新的功能,但我们可以稍后再改变主意,制作该方法

较好的更安全的;和更快。


只要可以使用值,就可以添加返回该值的方法。而不是:

int x = 1000 - 500

use

int x = 1000 - class_name.getValue();

用外行的话来说

假设我们需要存储此人的详细信息。此人具有姓名、年龄和性别字段。要做到这一点,需要创建姓名、年龄和性别的方法。现在,如果我们需要创建另一个人,就需要重新创建姓名、年龄和性别的方法。

我们可以使用getter和setter方法创建一个bean类(Person),而不是这样做。因此,明天我们只要在需要添加新人员时创建这个Bean类(Person类)的对象即可(见图)。因此,我们重用bean类的字段和方法,这要好得多。

虽然getter和setter不常用,但这些方法的使用也可以用于AOP/代理模式的使用。例如,对于审计变量,您可以使用AOP来审计任何值的更新。没有getter/setter,除了到处更改代码外,其他都是不可能的。我个人从未使用过AOP,但它显示了使用getter/setter的另一个优势。