是否可以公开不可变对象的状态?

2022-08-31 15:21:02

最近遇到了不可变对象的概念,我想知道控制对状态的访问的最佳实践。尽管我大脑中面向对象的部分使我想在看到公众成员时畏缩在恐惧中,但我没有看到这样的事情的技术问题:

public class Foo {
    public final int x;
    public final int y;

    public Foo( int x, int y) {
        this.x = x;
        this.y = y;
    }
}

我会觉得将字段声明为字段并为每个字段提供 getter 方法会更舒服,但是当状态显式只读时,这似乎过于复杂。private

提供对不可变对象状态的访问的最佳做法是什么?


答案 1

这完全取决于您将如何使用该对象。公共字段本质上并不是邪恶的,将所有内容都默认为公共字段是不好的。例如,java.awt.Point 类将其 x 和 y 字段设为公共字段,它们甚至不是最终字段。您的示例似乎很好地使用了公共字段,但话又说回来,您可能不希望公开另一个不可变对象的所有内部字段。没有包罗万象的规则。


答案 2

我过去也想过同样的想法,但通常最终会将变量设为私有并使用getter和setter,以便以后我仍然可以选择在保持相同接口的同时对实现进行更改。

这让我想起了我最近在罗伯特·C·马丁(Robert C. Martin)的《清洁代码》(Clean Code)中读到的一些东西。在第6章中,他给出了一个略有不同的观点。例如,在第95页上,他说

“对象将其数据隐藏在抽象后面,并公开对该数据进行操作的函数。数据结构暴露了他们的数据,没有有意义的功能。

在第100页上:

豆类的准封装似乎使一些OO纯粹主义者感觉更好,但通常不提供其他好处。

根据代码示例,Foo 类似乎是一个数据结构。因此,根据我从Clean Code中的讨论中了解到的内容(这不仅仅是我给出的两个引号),该类的目的是公开数据,而不是功能,并且拥有getter和setter可能没有多大好处。

同样,根据我的经验,我通常会继续使用私人数据的“豆”方法,与getters和setters一起使用。但话又说回来,从来没有人要求我写一本关于如何写更好的代码的书,所以也许马丁有话要说。