使用 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; }
而前者需要很少的样板代码。
实际上有许多充分的理由考虑使用访问器而不是直接暴露类的字段 - 除了封装的参数和使未来的更改更容易。
以下是我所知道的一些原因:
由于 2 周(月,年)从现在开始,当你意识到你的制定者需要的不仅仅是设置的值做多 ,你也意识到,财产已经在其他 238 类直接使用:-)
公共字段并不比除了返回字段并分配给它之外什么都不做的 getter / setter 对更差。首先,很明显(在大多数语言中)没有功能差异。任何差异必须与其他因素有关,如可维护性或可读性。
getter / setter 对经常提到的优点不是。有这样的说法,您可以更改实施,您的客户不必重新编译。据推测,setters 允许您稍后添加验证等功能,而您的客户甚至不需要了解它。然而,向 setter 添加验证是对其前提条件的改变, 违反了之前的合同 ,这很简单,“你可以把任何东西放在这里,你可以在以后从 getter 得到同样的东西”。
所以,既然您违反了合同,那么更改代码库中的每个文件都是您应该做的事情,而不是避免。如果你避免它,你会假设所有代码都假定这些方法的合同是不同的。
如果那不应该是合同,那么接口允许客户端将对象置于无效状态。 这与封装完全相反如果该字段从一开始就无法真正设置为任何东西,为什么从一开始就没有验证呢?
同样的论证适用于这些传递的 getter / setter 对的其他假设优势:如果你以后决定更改所设置的值,那么你就违反了合同。如果您覆盖派生类中的默认功能,超出了一些无害的修改(如日志记录或其他不可观察的行为),那么您就违反了基类的约定。这违反了 Liskov Substitutability Principle,这被视为 OO 的原则之一。
如果一个类对每个字段都有这些愚蠢的 getter 和 setter,那么它就是一个没有任何不变量的类, 没有契约 。这真的是面向对象的设计吗?如果所有课程都是那些吸气者和制定者,那么它只是一个愚蠢的数据持有者,而愚蠢的数据持有者应该看起来像愚蠢的数据持有者:
class Foo {
public:
int DaysLeft;
int ContestantNumber;
};
将传递 getter / setter 对添加到这样的类中不会增加任何值。其他类应该提供有意义的操作,而不仅仅是已经提供的字段的操作。这就是你如何定义和维护有用的不变量。
客户 :“我能用这个类的对象做什么?”
设计师 :“你可以读写几个变量。”
客户 :“哦...... 很酷,我猜?”
有理由使用 getter 和 setter,但如果这些原因不存在,那么以 false 封装之神的名义制作 getter / setter 对并不是一件好事。制作 getter 或 setter 的有效理由包括经常提到的事情,因为您可以在以后做出可能的更改,例如验证或不同的内部表示。或者值可能是客户端可读但不可写(例如,读取字典的大小),因此简单的 getter 是一个不错的选择。但是当你做出选择时,这些原因应该存在,而不仅仅是你以后想要的潜在事物。这是 YAGNI 的一个例子( 你不需要它 )。