当前位置: 首页 > 知识库问答 >
问题:

为什么使用 getter 和 setters/accessors?

子车鸿才
2023-03-14

使用getters和setters它们只获取和设置——而不是简单地使用这些变量的公共字段有什么好处?

如果getters和setters所做的不仅仅是简单的get/set,我可以很快搞清楚这一点,但是我不是100%清楚如何做到:

public String foo;

比任何更糟糕:

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

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

共有3个答案

屠锦
2023-03-14

公共字段并不比 getter/setter 对差,后者除了返回字段并分配给它之外什么都不做。首先,很明显(在大多数语言中)没有功能差异。任何差异都必须在其他因素上,例如可维护性或可读性。

经常提到的getter/setter对的一个优点不是这样。有一种说法是,您可以更改实现,而不必重新编译您的客户机。据推测,setter允许您稍后添加验证等功能,而您的客户甚至不需要知道。然而,向setter添加验证是对其先决条件的更改,违反了以前的约定,很简单,“您可以在这里放入任何内容,稍后您可以从getter获得相同的内容”。

所以,现在你违反了契约,更改代码库中的每个文件是你应该做的事情,而不是避免。如果你避免它,你就假设所有代码都假设这些方法的合约是不同的。

如果这不应该是契约,那么接口允许客户端将对象置于无效状态。这与封装完全相反。如果该字段从一开始就不能设置为任何值,为什么从一开始验证就没有设置?

同样的论点也适用于这些直通获取器/setter对的其他假定优点:如果您以后决定更改所设置的值,则违反了契约。如果重写派生类中的默认功能,则超出一些无害的修改(如日志记录或其他不可观察的行为),则会破坏基类的协定。这违反了Liskov可替代性原则,该原则被视为OO的原则之一。

如果一个类的每个字段都有这些哑的getter和setter,那么它就是一个没有不变量、没有契约的类。这真的是面向对象的设计吗?如果类只有这些getter和setter,那么它只是一个哑数据持有者,哑数据持有者应该看起来像哑数据持有者:

class Foo {
public:
    int DaysLeft;
    int ContestantNumber;
};

将直通getter/setter对添加到这样的类中不会增加任何价值。其他类应该提供有意义的操作,而不仅仅是字段已经提供的操作。这就是你如何定义和维护有用的不变量。

客户:“我可以用这个类的对象做什么?”< br> Designer:“您可以读写几个变量。”< br >客户:“哦...我猜很酷吧?”

有理由使用 getter 和 setters,但如果这些原因不存在,那么以假封装神的名义制作 getter/setter 对就不是一件好事。制作 getter 或 setter 的正当理由包括通常被提及为以后可以进行的潜在更改的事项,例如验证或不同的内部表示形式。或者,也许该值应该可由客户端读取但不可写(例如,读取字典的大小),因此简单的 getter 是一个不错的选择。但是,当你做出选择时,这些原因应该存在,而不仅仅是你以后可能想要的潜在东西。这是YAGNI的一个实例(你不会需要它)。

萧晓博
2023-03-14

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

慕阳
2023-03-14

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

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

    < li >封装与获取或设置属性相关的行为-这允许以后更容易地添加附加功能(如验证)。 < li >隐藏属性的内部表示,同时使用替代表示公开属性。 < li >使您的公共接口免于更改——允许公共接口在实现更改时保持不变,而不影响现有的使用者。 < li >控制属性的生存期和内存管理(处置)语义——这在非托管内存环境(如C或Objective-C)中尤其重要。 < li >为运行时属性更改提供调试拦截点——在某些语言中,如果没有这一点,调试何时何地属性更改为特定值会非常困难。 < li >改进了与针对属性getter/setter操作的库的互操作性——我想到了模仿、序列化和WPF。 < li >允许继承者通过重写getter/setter方法来更改属性行为和公开方式的语义。 < li >允许getter/setter作为lambda表达式而不是值传递。 < li > Getters和setters可以允许不同的访问级别,例如get可以是公共的,而set可以是受保护的。
 类似资料:
  • 问题内容: 我现在有两个类:RemindersDAO.java和ViewLocalReminders.java。 我试图访问ViewLocalReminders.java中的变量,并且试图从RemindersDAO.java调用它。我通过使用getter / setter方法组合来做到这一点。但是,由于某种原因,我的变量值在getter方法中一直设置为0。这是代码: ViewLocalRemind

  • 问题内容: 我现在有两个类:RemindersDAO.java和ViewLocalReminders.java。 我试图访问ViewLocalReminders.java中的变量,并且试图从RemindersDAO.java调用它。我通过使用getter / setter方法组合来做到这一点。但是,由于某种原因,我的变量值在getter方法中一直设置为0。这是代码: ViewLocalRemind

  • 问题内容: 简要阅读以上文章后,我发现getter和setter是糟糕的OO设计,应避免使用它们,因为它们与封装和数据隐藏相反。在这种情况下,创建对象时如何避免这种情况,以及如何将一个模型对象考虑在内。 如果需要使用吸气剂或吸气剂,还可以使用其他替代方法吗? 谢谢。 问题答案: 吸气或吸气器本身并不是很糟糕的OO设计。 不好的是编码实践,它会自动为每个单个成员包括一个getter和一个setter

  • 问题内容: 我这样做: 要么 我是Python的新手,所以我仍在探索语法,并且我想在此方面提供一些建议。 问题答案: 试试这个:Python属性 示例代码是:

  • 已安装Lombok v1.14.8“分支眼镜蛇”。http://projectlombok.org/ 将lombok添加到我的pom.xml: maven->更新项目。项目->清理

  • 问题内容: 我读过一些书,说为诸如和的变量创建setter和getter很好。例如: 但这有什么区别? 和 如果二传手和消气手更好,您能给我解释一下实际问题吗? 问题答案: 多个原因: 如果您允许像 shape.x = 90 那么您将来将无法添加任何逻辑来验证数据。 如果x不能小于100,就不能这样做,但是如果您有像 您不能在写入逻辑上添加诸如复制之类的内容(请参见CopyOnWriteArray