Getters and Setters是糟糕的OO设计?

时间:2010-04-30 21:10:24

标签: c# java oop encapsulation

Getters and Setters are bad

简单阅读上面的文章,我发现getter和setter是糟糕的OO设计,应该避免它们反对Encapsulation和Data Hiding。在这种情况下,如何在创建对象时避免它,以及如何将对象模型对象考虑在内。

如果需要吸气剂或固定剂,可以使用其他替代品吗?

感谢。

13 个答案:

答案 0 :(得分:48)

你错过了这一点。该文章的有效,重要的一点是:

  

不要求您提供所需的信息   做这项工作;问对象   有工作的信息   你。

Java风格的getter和setter扩散是无视这个建议的症状。

答案 1 :(得分:31)

吸气者或制定者本身也不错OO设计。

编码实践包括一个getter和一个setter,用于自动包含每个成员,无论是否需要getter / setter(加上公共成员不应公开) - 因为这基本上暴露了类的实现外界违反信息隐藏/抽象。有时这是由IDE自动完成的,这意味着这种做法比预期的要广泛得多。

答案 2 :(得分:5)

我相信在API中包含setter只有它们确实是类规范的一部分(即它与调用者的合同)。

应该隐藏与内部表示相关的任何其他数据成员,我至少看到两个主要原因:

1)如果公开内部表示,设计更改将来会出现问题,并且还需要更改API。

2)使用setter / getter公开数据成员时不要小心,这使得调用者很容易破坏类不变量。状态不一致的对象可能会导致很难分析的错误。

不幸的是,有些框架鼓励(有时需要)为所有内容添加setter / getter。

答案 3 :(得分:4)

吸气鬼和制定者本身并不坏。不好的做法是将任何领域变为私人领域,并为所有领域提供获取者/设定者,无论如何。

答案 4 :(得分:4)

是的,getter和setter是OOP中的反模式:http://www.yegor256.com/2014/09/16/getters-and-setters-are-evil.html。简而言之,它们不适合面向对象的范例,因为它们鼓励您将对象视为数据结构。这是一个重大的误解。

答案 5 :(得分:3)

我读它的方式,作者争辩说,盲目地在场地上放置吸气剂和制定者并不比仅仅将场地公之于众。

我认为作者认为,吸气剂和制定者应该稀疏地放置,并且要小心,因为OO的想法是对象应该限制他们只接触所需的东西。

答案 6 :(得分:2)

我会更进一步说,只有价值类型应该有吸气剂。每个值类型都应该是不可变的,并带有一个可变的构建器并具有setter。

如果您的值类型具有setter,则应在复制其他值后返回新实例。

Url.setAnchor(...)

会返回一个新的Url复制主机端口等,但会覆盖该锚点。

您的服务类型类不需要setter(在ctor中设置它们)并且肯定字体需要getter。您的邮件程序应该将主机/端口/等静态内容放在它的ctor中。如果我希望发送一封电子邮件,然后我将它发送给send(),我的代码就没有理由需要知道或想要或要求主机和其他配置值。这就是说创建一个类似下面的MailServer类是有意义的     // 值类型     MsilServer {        字符串主机        int端口        字符串用户名        串口密码//所有来自露丝的傻瓜     }     //工厂     邮件程序创建(MailServer)

答案 7 :(得分:1)

我建议你仔细阅读整篇文章,因为它提出了经过深思熟虑的论点和备选方案。问题本身太开放了,你在这里得到的答案只会是更多的意见。

答案 8 :(得分:1)

吸气剂和制定者只是方法。他们在做什么?他们将一个字段改为一个属性,这是一个重要的区别。

字段是对象中的一些状态数据。属性是外部可观察的特征,是对象合同的一部分。无论是直接地还是通过吸气剂/孵化器,在整个地方喷洒物体的内脏总是一个坏主意。设计不佳。但提出这一点,说吸气剂和制定者总是坏的?那只是一些没有良好品味的穷人程序员声称模糊的经验法则(他们一开始并不真正理解)是铸铁法。

就个人而言,我倾向于试图将房产保持为客户脚下不会意外变化的东西。 (类的客户端。)我将动态更改的唯一属性是他们无法写入的属性,即便如此,我也会尽量避免它。我觉得属性在很多方面都是控制客户端设置的实例行为的值,而不是类控制下的任意事物。 (这就是正常的领域......)

答案 9 :(得分:0)

来自文章:

  

什么时候访问者好吗?首先,就像我一样   前面讨论过,没关系   用于返回对象的方法   对象的接口   实现因为那个接口   隔离你的变化   实施课程。这种   方法(返回接口   参考)并不是真正的“吸气剂”   只是一种方法的感觉   提供对字段的访问。如果你   改变提供者的内部   实施,你只需改变   返回对象的定义   适应变化。你还在   保护使用的外部代码   对象通过它的界面。

换句话说,当必要时,可以使用getter和setter方法的接口来保持封装。一般来说,为返回类型或形式参数指定接口是一种好习惯。

答案 10 :(得分:0)

还有其他文章说它们是好的设计。 但答案是这样的: 根据使用情况,getXXX和setXXX的好坏。 这些方法确实使很多事情变得更容易。所以,如果有一篇文章说这是一个糟糕的设计我认为;它只是试图对这个想法过于刻板。

这些方法的最大用途之一是在很多框架中并用作反射机制。

所以不要完全避免使用它们,而是......明智地使用它。

感谢 Ayusman

答案 11 :(得分:0)

  

Getter和Setter是糟糕的OO设计?

只有在不假思索的情况下使用

如果您要创建一个值对象来传输数据,那么它们就没问题了。

如果您正在创建一个更重要的对象,那么它们就不应该存在。例如,查看ArrayList接口 * 。你没有看到Object[] getElementData(),因为这会破坏封装(有些人可能会使底层数组发生变形)。

* 我指的是类的公共接口(类定义公开的方法)

答案 12 :(得分:0)

在适当的条件下,Getters / Setters非常合适。但是,质量Get / Set是错误的。

然而,我有点困惑。您标记了Java,但该材料并非特别特定于Java(仅限示例)。值得注意的是,在C ++中(最好用0x完成),其中许多问题都不存在。如果你想将你的界面从long更改为int,那么在decltype,templates和auto之间这很容易实现,这就是为什么这样的结构摇滚。 Typedef效果也很好。