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