How I Would Re-design equals()

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

我想稍微吐槽一下Java的设计,尤其是关于Object.equals()Comparable.compareTo()这两个方法。多年来,我一直讨厌它们,因为无论我如何努力去喜欢它们,方法内部看起来都很丑陋。现在我知道了究竟哪里出了问题,以及我如何更好地设计这个”对象对比”机制。

假设我们有一个简单的原始类Weight,其对象表示某物体的重量(以千克为单位)。

接下来,我们希望两个重量相同的物体彼此相等:

以下是这种方法的示例:

这里的丑陋之处首先是使用instanceof进行类型转换。第二个问题是我们触及了传入对象的内部。这种设计使得Weight的多态行为变得不可能。除了Weight类的实例,我们无法向equals()方法传递其他任何东西。我们无法将其转化为一个接口并引入多个实现。

这段代码将无法工作:

问题在于一个对象决定另一个对象是否相等。这不可避免地导致需要访问私有属性来进行实际比较。

解决方案是什么呢?

这就是我提供的解决方案。无论我们要比较什么类型的数据,比较的都是两个数字值。无论是比较重量与重量,文本与文本,还是用户与用户—我们的CPU只能比较数字。因此,我们引入一个新的接口Digitizable

接下来,我们引入一个新的类Comparison,它两个字节流的比较(我不确定代码是否完美,我在这里进行了测试,欢迎通过拉取请求进行改进和贡献)。

现在,我们需要Weight来实现Digitizable

最后,这是我们如何进行比较的:

这个 v 的值可以是 -101。在这个特定的情况下,它将是 -1,因为 400 小于 500

不再违反封装,不再需要类型转换,在 equals()compareTo() 方法中也不再有丑陋的代码。Comparison 类将适用于所有可能的类型。为了变得可比较,我们的所有对象只需要实现 Digitizable 接口,并“提供”它们的字节供检查/比较。

这种方法实际上与我之前描述的打印机非常接近。

Translated by ChatGPT gpt-3.5-turbo/42 on 2023-12-15 at 06:19

sixnines availability badge   GitHub stars