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. Мы просто не можем передать что-либо еще в метод equals(), кроме экземпляра класса Weight. Мы не можем превратить его в интерфейс и ввести несколько его реализаций:

Этот код не будет работать:

Проблема заключается в том, что один объект решает, равны ли они друг другу. Это неизбежно ведет к необходимости обращаться к приватным атрибутам для выполнения фактического сравнения.

Какое решение?

Вот что я предлагаю. Любое сравнение, независимо от типов, о которых мы говорим, заключается в сравнении двух цифровых значений. Мы можем сравнивать либо вес с весом, текст с текстом, либо пользователя с пользователем - наши ЦП могут сравнивать только числа. Таким образом, мы вводим новый интерфейс Digitizable:

Далее мы представляем новый класс Comparison, который является сравнением двух потоков байтов (Я не уверен, что код идеален, я его тестировал здесь, не стесняйтесь улучшать и вносить вклад с помощью pull-запроса).

Сейчас нам нужно 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:20

sixnines availability badge   GitHub stars