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
的值可以是 -1
、0
或 1
。在这个特定的情况下,它将是 -1
,因为 400
小于 500
。
不再违反封装,不再需要类型转换,在 equals()
和 compareTo()
方法中也不再有丑陋的代码。Comparison
类将适用于所有可能的类型。为了变得可比较,我们的所有对象只需要实现 Digitizable
接口,并“提供”它们的字节供检查/比较。
这种方法实际上与我之前描述的打印机非常接近。
Translated by ChatGPT gpt-3.5-turbo/42 on 2023-12-15 at 06:19