Effective Java: Общие для всех объектов методы

Следующая глава книги.

Item 8. Соблюдайте контракт метода equals, переопределяя его.


Случаи, когда переопределять метод equals не требуется:
  • каждый экземпляр класса по определению уникален;
  • нет необходимости сравнивать экземпляры "логически";
  • суперкласс переопределил этот метод, и его поведение подходит и для данного подкласса;
  • класс приватный или package-private и вы уверены, что метод equals не используется.
Метод equals необходимо переопределять, если могут существовать различные экземпляры класса, логически эквивалентные друг другу.
В конце параграфа приводится рецепт хорошей реализации метода и следующие советы:
  • всегда следует переопределять метод hashCode при переопределении equals;
  • не надо увлекаться: к примеру, класс File не углубляется до проверки, указывают ли различные символические ссылки на один и тот же файл;
  • объявление метода equals стоит писать очень внимательно, в противном случае вместо override можно сделать overload и ошибку будет довольно сложно найти.

Item 9. Всегда переопределяйте метод hashCode при переопределении equals.

Эквивалентные объекты должны иметь одиннаковый хэш-код. Несоблюдение этого правила приведёт к нарушению работы, как минимум, некоторых коллекций.
В параграфе приводится ряд рекомендаций по написанию удачной хэш-функции.

Item 10. Всегда переопределяйте метод toString.

Это добавляет удобства при использовании класса, так как строка (707) 867-5309 говорит гораздо больше, чем PhoneNumber@163b91.
Формат возвращаемой строки может быть как описан, так и не описан в документации класса. Естественно, будучи объявленным в документации, формат не сможет быть изменён в дальнейшем. В любом случае следует обеспечивать программный доступ к полям, используемым в toString, чтобы не провоцировать клиентский код парсить строку, возвращаемую последним.

Item 11. Переопределяйте метод clone с умом.

Этот параграф содержит слишком много пунктов, которые следовало бы написать сюда, поэтому я этого делать не буду. Если нужно спроектировать объект с возможностью клонирования, придётся перечитать параграф целиком. Однако, отдельно хотелось бы отметить следующие факты:
  • При переопределении метода clone в non-final классе всегда следует возвращать объект, полученный вызовом super.clone, только тогда он будет иметь правильный тип.
  • Если класс содержит ссылки на изменяемые (mutable) объекты, то при клонировании эти объекты должны быть рекурсивно склонированы вместо простого копирования ссылок на них, которое происходит по умолчанию. Общее правило таково, что клон и оригинал не должны иметь общих внутренностей, кроме неизменяемых (immutable).
  • Иногда можно обойтись копирующим конструктором, это гораздо проще.

Item 12. Подумайте об имплементации интерфейса Comparable.

Если для объектов рассматриваемого класса существует некоторый естесственный порядок (natural order), имеет смысл имплементировать этот интерфейс. Небольшие усилия, затраченные на создание функции сравнения, открывают для класса всю мощь стандартных алгоритмов и коллекций, требующих существование этого порядка. Обычно этот интерфейс имплементируют классы, представляющие какое-либо значение: число, дату и время и т.д.

Комментариев нет:

Отправить комментарий